
<!DOCTYPE html>
<html>
  <head>
<!--    <meta http-equiv="Content-Security-Policy" content="script-src *  'self' 'unsafe-inline' 'unsafe-eval' default-src * data: blob: vscode-webview-resource: ;"> -->
  <meta http-equiv="Content-Security-Policy" content="default-src * 'unsafe-inline' 'unsafe-eval' data: blob:; script-src * 'unsafe-inline' 'unsafe-eval' data: blob:; style-src * 'unsafe-inline' 'unsafe-eval' data: blob:; img-src * 'unsafe-inline' 'unsafe-eval' data: blob:; connect-src * 'unsafe-inline' 'unsafe-eval' data: blob:; font-src * 'unsafe-inline' 'unsafe-eval' data: blob:; object-src * 'unsafe-inline' 'unsafe-eval' data: blob:; media-src * 'unsafe-inline' 'unsafe-eval' data: blob:; frame-src * 'unsafe-inline' 'unsafe-eval' data: blob:;">
<!--    <meta http-equiv="Content-Security-Policy" content="default-src * data: blob: vscode-webview-resource: 'unsafe-inline' 'unsafe-eval' ; script-src * data: blob: vscode-webview-resource: 'unsafe-inline' 'unsafe-eval';"> -->
    <title>Scalene</title>
    <link rel="icon" href="https://raw.githubusercontent.com/plasma-umass/scalene/master/scalene/scalene-gui/favicon.ico" type="image/x-icon">
    <!-- Latest compiled and minified CSS -->
    <script src="https://code.jquery.com/jquery-3.6.0.slim.min.js"></script>
    
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
    <script src="https://sdk.amazonaws.com/js/aws-sdk-2.1543.0.min.js"></script>
    <style>
body { 
  padding: 0 0 90px 0;
}
    </style>
    <style>
/* PrismJS 1.26.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+python&plugins=normalize-whitespace */
/**
 * prism.js default theme for JavaScript, CSS and HTML
 * Based on dabblet (http://dabblet.com)
 * @author Lea Verou
 */

code[class*="language-"],
pre[class*="language-"] {
	color: black;
	background: none;
	text-shadow: 0 1px white;
	font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
	font-size: 1em;
	text-align: left;
	white-space: pre;
	word-spacing: normal;
	word-break: normal;
	word-wrap: normal;
	line-height: 1.5;

	-moz-tab-size: 4;
	-o-tab-size: 4;
	tab-size: 4;

	-webkit-hyphens: none;
	-moz-hyphens: none;
	-ms-hyphens: none;
	hyphens: none;
}

pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
	text-shadow: none;
	background: #b3d4fc;
}

pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
code[class*="language-"]::selection, code[class*="language-"] ::selection {
	text-shadow: none;
	background: #b3d4fc;
}

@media print {
	code[class*="language-"],
	pre[class*="language-"] {
		text-shadow: none;
	}
}

/* Code blocks */
pre[class*="language-"] {
	padding: 1em;
	margin: .5em 0;
	overflow: auto;
}

:not(pre) > code[class*="language-"],
pre[class*="language-"] {
	background: #f5f2f0;
}

/* Inline code */
:not(pre) > code[class*="language-"] {
	padding: .1em;
	border-radius: .3em;
	white-space: normal;
}

.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
	color: slategray;
}

.token.punctuation {
	color: #999;
}

.token.namespace {
	opacity: .7;
}

.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
	color: #905;
}

.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
	color: #690;
}

.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
	color: #9a6e3a;
	/* This background color was intended by the author of this theme. */
	background: hsla(0, 0%, 100%, .5);
}

.token.atrule,
.token.attr-value,
.token.keyword {
	color: #07a;
}

.token.function,
.token.class-name {
	color: #DD4A68;
}

.token.regex,
.token.important,
.token.variable {
	color: #e90;
}

.token.important,
.token.bold {
	font-weight: bold;
}
.token.italic {
	font-style: italic;
}

.token.entity {
	cursor: help;
}

      
    </style>
    <style>
      .table-condensed>thead>tr>th, .table-condensed>tbody>tr>th, .table-condensed>tfoot>tr>th, .table-condensed>thead>tr>td, .table-condensed>tbody>tr>td, .table-condensed>tfoot>tr>td{
	  padding: 1px; border-spacing: 0px; border:none;
      }
    form label:hover, form button:hover {
      background-color: black;
      color: white;
    }

    form label:active, form button:active {
      background-color: blue;
      color: white;
    }      
    </style>
    <!-- Global site tag (gtag.js) - Google Analytics -->
    <script async src="https://www.googletagmanager.com/gtag/js?id=G-4JXPHEBMTY"></script>
    <script>
      window.dataLayer = window.dataLayer || [];
      function gtag(){dataLayer.push(arguments);}
      gtag('js', new Date());
      
      gtag('config', 'G-4JXPHEBMTY');
    </script>

    <script>
/* PrismJS 1.26.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+python&plugins=normalize-whitespace */
/// <reference lib="WebWorker"/>

var _self =
  typeof window !== "undefined"
    ? window // if in browser
    : typeof WorkerGlobalScope !== "undefined" &&
      self instanceof WorkerGlobalScope
    ? self // if in worker
    : {}; // if in node js

/**
 * Prism: Lightweight, robust, elegant syntax highlighting
 *
 * @license MIT <https://opensource.org/licenses/MIT>
 * @author Lea Verou <https://lea.verou.me>
 * @namespace
 * @public
 */
var Prism = (function (_self) {
  // Private helper vars
  var lang = /(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i;
  var uniqueId = 0;

  // The grammar object for plaintext
  var plainTextGrammar = {};

  var _ = {
    /**
     * By default, Prism will attempt to highlight all code elements (by calling {@link Prism.highlightAll}) on the
     * current page after the page finished loading. This might be a problem if e.g. you wanted to asynchronously load
     * additional languages or plugins yourself.
     *
     * By setting this value to `true`, Prism will not automatically highlight all code elements on the page.
     *
     * You obviously have to change this value before the automatic highlighting started. To do this, you can add an
     * empty Prism object into the global scope before loading the Prism script like this:
     *
     * ```js
     * window.Prism = window.Prism || {};
     * Prism.manual = true;
     * // add a new <script> to load Prism's script
     * ```
     *
     * @default false
     * @type {boolean}
     * @memberof Prism
     * @public
     */
    manual: _self.Prism && _self.Prism.manual,
    /**
     * By default, if Prism is in a web worker, it assumes that it is in a worker it created itself, so it uses
     * `addEventListener` to communicate with its parent instance. However, if you're using Prism manually in your
     * own worker, you don't want it to do this.
     *
     * By setting this value to `true`, Prism will not add its own listeners to the worker.
     *
     * You obviously have to change this value before Prism executes. To do this, you can add an
     * empty Prism object into the global scope before loading the Prism script like this:
     *
     * ```js
     * window.Prism = window.Prism || {};
     * Prism.disableWorkerMessageHandler = true;
     * // Load Prism's script
     * ```
     *
     * @default false
     * @type {boolean}
     * @memberof Prism
     * @public
     */
    disableWorkerMessageHandler:
      _self.Prism && _self.Prism.disableWorkerMessageHandler,

    /**
     * A namespace for utility methods.
     *
     * All function in this namespace that are not explicitly marked as _public_ are for __internal use only__ and may
     * change or disappear at any time.
     *
     * @namespace
     * @memberof Prism
     */
    util: {
      encode: function encode(tokens) {
        if (tokens instanceof Token) {
          return new Token(tokens.type, encode(tokens.content), tokens.alias);
        } else if (Array.isArray(tokens)) {
          return tokens.map(encode);
        } else {
          return tokens
            .replace(/&/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/\u00a0/g, " ");
        }
      },

      /**
       * Returns the name of the type of the given value.
       *
       * @param {any} o
       * @returns {string}
       * @example
       * type(null)      === 'Null'
       * type(undefined) === 'Undefined'
       * type(123)       === 'Number'
       * type('foo')     === 'String'
       * type(true)      === 'Boolean'
       * type([1, 2])    === 'Array'
       * type({})        === 'Object'
       * type(String)    === 'Function'
       * type(/abc+/)    === 'RegExp'
       */
      type: function (o) {
        return Object.prototype.toString.call(o).slice(8, -1);
      },

      /**
       * Returns a unique number for the given object. Later calls will still return the same number.
       *
       * @param {Object} obj
       * @returns {number}
       */
      objId: function (obj) {
        if (!obj["__id"]) {
          Object.defineProperty(obj, "__id", { value: ++uniqueId });
        }
        return obj["__id"];
      },

      /**
       * Creates a deep clone of the given object.
       *
       * The main intended use of this function is to clone language definitions.
       *
       * @param {T} o
       * @param {Record<number, any>} [visited]
       * @returns {T}
       * @template T
       */
      clone: function deepClone(o, visited) {
        visited = visited || {};

        var clone;
        var id;
        switch (_.util.type(o)) {
          case "Object":
            id = _.util.objId(o);
            if (visited[id]) {
              return visited[id];
            }
            clone = /** @type {Record<string, any>} */ ({});
            visited[id] = clone;

            for (var key in o) {
              if (o.hasOwnProperty(key)) {
                clone[key] = deepClone(o[key], visited);
              }
            }

            return /** @type {any} */ (clone);

          case "Array":
            id = _.util.objId(o);
            if (visited[id]) {
              return visited[id];
            }
            clone = [];
            visited[id] = clone;

            /** @type {Array} */ (/** @type {any} */ (o)).forEach(function (
              v,
              i
            ) {
              clone[i] = deepClone(v, visited);
            });

            return /** @type {any} */ (clone);

          default:
            return o;
        }
      },

      /**
       * Returns the Prism language of the given element set by a `language-xxxx` or `lang-xxxx` class.
       *
       * If no language is set for the element or the element is `null` or `undefined`, `none` will be returned.
       *
       * @param {Element} element
       * @returns {string}
       */
      getLanguage: function (element) {
        while (element) {
          var m = lang.exec(element.className);
          if (m) {
            return m[1].toLowerCase();
          }
          element = element.parentElement;
        }
        return "none";
      },

      /**
       * Sets the Prism `language-xxxx` class of the given element.
       *
       * @param {Element} element
       * @param {string} language
       * @returns {void}
       */
      setLanguage: function (element, language) {
        // remove all `language-xxxx` classes
        // (this might leave behind a leading space)
        element.className = element.className.replace(RegExp(lang, "gi"), "");

        // add the new `language-xxxx` class
        // (using `classList` will automatically clean up spaces for us)
        element.classList.add("language-" + language);
      },

      /**
       * Returns the script element that is currently executing.
       *
       * This does __not__ work for line script element.
       *
       * @returns {HTMLScriptElement | null}
       */
      currentScript: function () {
        if (typeof document === "undefined") {
          return null;
        }
        if (
          "currentScript" in document &&
          1 < 2 /* hack to trip TS' flow analysis */
        ) {
          return /** @type {any} */ (document.currentScript);
        }

        // IE11 workaround
        // we'll get the src of the current script by parsing IE11's error stack trace
        // this will not work for inline scripts

        try {
          throw new Error();
        } catch (err) {
          // Get file src url from stack. Specifically works with the format of stack traces in IE.
          // A stack will look like this:
          //
          // Error
          //    at _.util.currentScript (http://localhost/components/prism-core.js:119:5)
          //    at Global code (http://localhost/components/prism-core.js:606:1)

          var src = (/at [^(\r\n]*\((.*):[^:]+:[^:]+\)$/i.exec(err.stack) ||
            [])[1];
          if (src) {
            var scripts = document.getElementsByTagName("script");
            for (var i in scripts) {
              if (scripts[i].src == src) {
                return scripts[i];
              }
            }
          }
          return null;
        }
      },

      /**
       * Returns whether a given class is active for `element`.
       *
       * The class can be activated if `element` or one of its ancestors has the given class and it can be deactivated
       * if `element` or one of its ancestors has the negated version of the given class. The _negated version_ of the
       * given class is just the given class with a `no-` prefix.
       *
       * Whether the class is active is determined by the closest ancestor of `element` (where `element` itself is
       * closest ancestor) that has the given class or the negated version of it. If neither `element` nor any of its
       * ancestors have the given class or the negated version of it, then the default activation will be returned.
       *
       * In the paradoxical situation where the closest ancestor contains __both__ the given class and the negated
       * version of it, the class is considered active.
       *
       * @param {Element} element
       * @param {string} className
       * @param {boolean} [defaultActivation=false]
       * @returns {boolean}
       */
      isActive: function (element, className, defaultActivation) {
        var no = "no-" + className;

        while (element) {
          var classList = element.classList;
          if (classList.contains(className)) {
            return true;
          }
          if (classList.contains(no)) {
            return false;
          }
          element = element.parentElement;
        }
        return !!defaultActivation;
      },
    },

    /**
     * This namespace contains all currently loaded languages and the some helper functions to create and modify languages.
     *
     * @namespace
     * @memberof Prism
     * @public
     */
    languages: {
      /**
       * The grammar for plain, unformatted text.
       */
      plain: plainTextGrammar,
      plaintext: plainTextGrammar,
      text: plainTextGrammar,
      txt: plainTextGrammar,

      /**
       * Creates a deep copy of the language with the given id and appends the given tokens.
       *
       * If a token in `redef` also appears in the copied language, then the existing token in the copied language
       * will be overwritten at its original position.
       *
       * ## Best practices
       *
       * Since the position of overwriting tokens (token in `redef` that overwrite tokens in the copied language)
       * doesn't matter, they can technically be in any order. However, this can be confusing to others that trying to
       * understand the language definition because, normally, the order of tokens matters in Prism grammars.
       *
       * Therefore, it is encouraged to order overwriting tokens according to the positions of the overwritten tokens.
       * Furthermore, all non-overwriting tokens should be placed after the overwriting ones.
       *
       * @param {string} id The id of the language to extend. This has to be a key in `Prism.languages`.
       * @param {Grammar} redef The new tokens to append.
       * @returns {Grammar} The new language created.
       * @public
       * @example
       * Prism.languages['css-with-colors'] = Prism.languages.extend('css', {
       *     // Prism.languages.css already has a 'comment' token, so this token will overwrite CSS' 'comment' token
       *     // at its original position
       *     'comment': { ... },
       *     // CSS doesn't have a 'color' token, so this token will be appended
       *     'color': /\b(?:red|green|blue)\b/
       * });
       */
      extend: function (id, redef) {
        var lang = _.util.clone(_.languages[id]);

        for (var key in redef) {
          lang[key] = redef[key];
        }

        return lang;
      },

      /**
       * Inserts tokens _before_ another token in a language definition or any other grammar.
       *
       * ## Usage
       *
       * This helper method makes it easy to modify existing languages. For example, the CSS language definition
       * not only defines CSS highlighting for CSS documents, but also needs to define highlighting for CSS embedded
       * in HTML through `<style>` elements. To do this, it needs to modify `Prism.languages.markup` and add the
       * appropriate tokens. However, `Prism.languages.markup` is a regular JavaScript object literal, so if you do
       * this:
       *
       * ```js
       * Prism.languages.markup.style = {
       *     // token
       * };
       * ```
       *
       * then the `style` token will be added (and processed) at the end. `insertBefore` allows you to insert tokens
       * before existing tokens. For the CSS example above, you would use it like this:
       *
       * ```js
       * Prism.languages.insertBefore('markup', 'cdata', {
       *     'style': {
       *         // token
       *     }
       * });
       * ```
       *
       * ## Special cases
       *
       * If the grammars of `inside` and `insert` have tokens with the same name, the tokens in `inside`'s grammar
       * will be ignored.
       *
       * This behavior can be used to insert tokens after `before`:
       *
       * ```js
       * Prism.languages.insertBefore('markup', 'comment', {
       *     'comment': Prism.languages.markup.comment,
       *     // tokens after 'comment'
       * });
       * ```
       *
       * ## Limitations
       *
       * The main problem `insertBefore` has to solve is iteration order. Since ES2015, the iteration order for object
       * properties is guaranteed to be the insertion order (except for integer keys) but some browsers behave
       * differently when keys are deleted and re-inserted. So `insertBefore` can't be implemented by temporarily
       * deleting properties which is necessary to insert at arbitrary positions.
       *
       * To solve this problem, `insertBefore` doesn't actually insert the given tokens into the target object.
       * Instead, it will create a new object and replace all references to the target object with the new one. This
       * can be done without temporarily deleting properties, so the iteration order is well-defined.
       *
       * However, only references that can be reached from `Prism.languages` or `insert` will be replaced. I.e. if
       * you hold the target object in a variable, then the value of the variable will not change.
       *
       * ```js
       * var oldMarkup = Prism.languages.markup;
       * var newMarkup = Prism.languages.insertBefore('markup', 'comment', { ... });
       *
       * assert(oldMarkup !== Prism.languages.markup);
       * assert(newMarkup === Prism.languages.markup);
       * ```
       *
       * @param {string} inside The property of `root` (e.g. a language id in `Prism.languages`) that contains the
       * object to be modified.
       * @param {string} before The key to insert before.
       * @param {Grammar} insert An object containing the key-value pairs to be inserted.
       * @param {Object<string, any>} [root] The object containing `inside`, i.e. the object that contains the
       * object to be modified.
       *
       * Defaults to `Prism.languages`.
       * @returns {Grammar} The new grammar object.
       * @public
       */
      insertBefore: function (inside, before, insert, root) {
        root = root || /** @type {any} */ (_.languages);
        var grammar = root[inside];
        /** @type {Grammar} */
        var ret = {};

        for (var token in grammar) {
          if (grammar.hasOwnProperty(token)) {
            if (token == before) {
              for (var newToken in insert) {
                if (insert.hasOwnProperty(newToken)) {
                  ret[newToken] = insert[newToken];
                }
              }
            }

            // Do not insert token which also occur in insert. See #1525
            if (!insert.hasOwnProperty(token)) {
              ret[token] = grammar[token];
            }
          }
        }

        var old = root[inside];
        root[inside] = ret;

        // Update references in other language definitions
        _.languages.DFS(_.languages, function (key, value) {
          if (value === old && key != inside) {
            this[key] = ret;
          }
        });

        return ret;
      },

      // Traverse a language definition with Depth First Search
      DFS: function DFS(o, callback, type, visited) {
        visited = visited || {};

        var objId = _.util.objId;

        for (var i in o) {
          if (o.hasOwnProperty(i)) {
            callback.call(o, i, o[i], type || i);

            var property = o[i];
            var propertyType = _.util.type(property);

            if (propertyType === "Object" && !visited[objId(property)]) {
              visited[objId(property)] = true;
              DFS(property, callback, null, visited);
            } else if (propertyType === "Array" && !visited[objId(property)]) {
              visited[objId(property)] = true;
              DFS(property, callback, i, visited);
            }
          }
        }
      },
    },

    plugins: {},

    /**
     * This is the most high-level function in Prism’s API.
     * It fetches all the elements that have a `.language-xxxx` class and then calls {@link Prism.highlightElement} on
     * each one of them.
     *
     * This is equivalent to `Prism.highlightAllUnder(document, async, callback)`.
     *
     * @param {boolean} [async=false] Same as in {@link Prism.highlightAllUnder}.
     * @param {HighlightCallback} [callback] Same as in {@link Prism.highlightAllUnder}.
     * @memberof Prism
     * @public
     */
    highlightAll: function (async, callback) {
      _.highlightAllUnder(document, async, callback);
    },

    /**
     * Fetches all the descendants of `container` that have a `.language-xxxx` class and then calls
     * {@link Prism.highlightElement} on each one of them.
     *
     * The following hooks will be run:
     * 1. `before-highlightall`
     * 2. `before-all-elements-highlight`
     * 3. All hooks of {@link Prism.highlightElement} for each element.
     *
     * @param {ParentNode} container The root element, whose descendants that have a `.language-xxxx` class will be highlighted.
     * @param {boolean} [async=false] Whether each element is to be highlighted asynchronously using Web Workers.
     * @param {HighlightCallback} [callback] An optional callback to be invoked on each element after its highlighting is done.
     * @memberof Prism
     * @public
     */
    highlightAllUnder: function (container, async, callback) {
      var env = {
        callback: callback,
        container: container,
        selector:
          'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code',
      };

      _.hooks.run("before-highlightall", env);

      env.elements = Array.prototype.slice.apply(
        env.container.querySelectorAll(env.selector)
      );

      _.hooks.run("before-all-elements-highlight", env);

      for (var i = 0, element; (element = env.elements[i++]); ) {
        _.highlightElement(element, async === true, env.callback);
      }
    },

    /**
     * Highlights the code inside a single element.
     *
     * The following hooks will be run:
     * 1. `before-sanity-check`
     * 2. `before-highlight`
     * 3. All hooks of {@link Prism.highlight}. These hooks will be run by an asynchronous worker if `async` is `true`.
     * 4. `before-insert`
     * 5. `after-highlight`
     * 6. `complete`
     *
     * Some the above hooks will be skipped if the element doesn't contain any text or there is no grammar loaded for
     * the element's language.
     *
     * @param {Element} element The element containing the code.
     * It must have a class of `language-xxxx` to be processed, where `xxxx` is a valid language identifier.
     * @param {boolean} [async=false] Whether the element is to be highlighted asynchronously using Web Workers
     * to improve performance and avoid blocking the UI when highlighting very large chunks of code. This option is
     * [disabled by default](https://prismjs.com/faq.html#why-is-asynchronous-highlighting-disabled-by-default).
     *
     * Note: All language definitions required to highlight the code must be included in the main `prism.js` file for
     * asynchronous highlighting to work. You can build your own bundle on the
     * [Download page](https://prismjs.com/download.html).
     * @param {HighlightCallback} [callback] An optional callback to be invoked after the highlighting is done.
     * Mostly useful when `async` is `true`, since in that case, the highlighting is done asynchronously.
     * @memberof Prism
     * @public
     */
    highlightElement: function (element, async, callback) {
      // Find language
      var language = _.util.getLanguage(element);
      var grammar = _.languages[language];

      // Set language on the element, if not present
      _.util.setLanguage(element, language);

      // Set language on the parent, for styling
      var parent = element.parentElement;
      if (parent && parent.nodeName.toLowerCase() === "pre") {
        _.util.setLanguage(parent, language);
      }

      var code = element.textContent;

      var env = {
        element: element,
        language: language,
        grammar: grammar,
        code: code,
      };

      function insertHighlightedCode(highlightedCode) {
        env.highlightedCode = highlightedCode;

        _.hooks.run("before-insert", env);

        env.element.innerHTML = env.highlightedCode;

        _.hooks.run("after-highlight", env);
        _.hooks.run("complete", env);
        callback && callback.call(env.element);
      }

      _.hooks.run("before-sanity-check", env);

      // plugins may change/add the parent/element
      parent = env.element.parentElement;
      if (
        parent &&
        parent.nodeName.toLowerCase() === "pre" &&
        !parent.hasAttribute("tabindex")
      ) {
        parent.setAttribute("tabindex", "0");
      }

      if (!env.code) {
        _.hooks.run("complete", env);
        callback && callback.call(env.element);
        return;
      }

      _.hooks.run("before-highlight", env);

      if (!env.grammar) {
        insertHighlightedCode(_.util.encode(env.code));
        return;
      }

      if (async && _self.Worker) {
        var worker = new Worker(_.filename);

        worker.onmessage = function (evt) {
          insertHighlightedCode(evt.data);
        };

        worker.postMessage(
          JSON.stringify({
            language: env.language,
            code: env.code,
            immediateClose: true,
          })
        );
      } else {
        insertHighlightedCode(_.highlight(env.code, env.grammar, env.language));
      }
    },

    /**
     * Low-level function, only use if you know what you’re doing. It accepts a string of text as input
     * and the language definitions to use, and returns a string with the HTML produced.
     *
     * The following hooks will be run:
     * 1. `before-tokenize`
     * 2. `after-tokenize`
     * 3. `wrap`: On each {@link Token}.
     *
     * @param {string} text A string with the code to be highlighted.
     * @param {Grammar} grammar An object containing the tokens to use.
     *
     * Usually a language definition like `Prism.languages.markup`.
     * @param {string} language The name of the language definition passed to `grammar`.
     * @returns {string} The highlighted HTML.
     * @memberof Prism
     * @public
     * @example
     * Prism.highlight('var foo = true;', Prism.languages.javascript, 'javascript');
     */
    highlight: function (text, grammar, language) {
      var env = {
        code: text,
        grammar: grammar,
        language: language,
      };
      _.hooks.run("before-tokenize", env);
      env.tokens = _.tokenize(env.code, env.grammar);
      _.hooks.run("after-tokenize", env);
      return Token.stringify(_.util.encode(env.tokens), env.language);
    },

    /**
     * This is the heart of Prism, and the most low-level function you can use. It accepts a string of text as input
     * and the language definitions to use, and returns an array with the tokenized code.
     *
     * When the language definition includes nested tokens, the function is called recursively on each of these tokens.
     *
     * This method could be useful in other contexts as well, as a very crude parser.
     *
     * @param {string} text A string with the code to be highlighted.
     * @param {Grammar} grammar An object containing the tokens to use.
     *
     * Usually a language definition like `Prism.languages.markup`.
     * @returns {TokenStream} An array of strings and tokens, a token stream.
     * @memberof Prism
     * @public
     * @example
     * let code = `var foo = 0;`;
     * let tokens = Prism.tokenize(code, Prism.languages.javascript);
     * tokens.forEach(token => {
     *     if (token instanceof Prism.Token && token.type === 'number') {
     *         console.log(`Found numeric literal: ${token.content}`);
     *     }
     * });
     */
    tokenize: function (text, grammar) {
      var rest = grammar.rest;
      if (rest) {
        for (var token in rest) {
          grammar[token] = rest[token];
        }

        delete grammar.rest;
      }

      var tokenList = new LinkedList();
      addAfter(tokenList, tokenList.head, text);

      matchGrammar(text, tokenList, grammar, tokenList.head, 0);

      return toArray(tokenList);
    },

    /**
     * @namespace
     * @memberof Prism
     * @public
     */
    hooks: {
      all: {},

      /**
       * Adds the given callback to the list of callbacks for the given hook.
       *
       * The callback will be invoked when the hook it is registered for is run.
       * Hooks are usually directly run by a highlight function but you can also run hooks yourself.
       *
       * One callback function can be registered to multiple hooks and the same hook multiple times.
       *
       * @param {string} name The name of the hook.
       * @param {HookCallback} callback The callback function which is given environment variables.
       * @public
       */
      add: function (name, callback) {
        var hooks = _.hooks.all;

        hooks[name] = hooks[name] || [];

        hooks[name].push(callback);
      },

      /**
       * Runs a hook invoking all registered callbacks with the given environment variables.
       *
       * Callbacks will be invoked synchronously and in the order in which they were registered.
       *
       * @param {string} name The name of the hook.
       * @param {Object<string, any>} env The environment variables of the hook passed to all callbacks registered.
       * @public
       */
      run: function (name, env) {
        var callbacks = _.hooks.all[name];

        if (!callbacks || !callbacks.length) {
          return;
        }

        for (var i = 0, callback; (callback = callbacks[i++]); ) {
          callback(env);
        }
      },
    },

    Token: Token,
  };
  _self.Prism = _;

  // Typescript note:
  // The following can be used to import the Token type in JSDoc:
  //
  //   @typedef {InstanceType<import("./prism-core")["Token"]>} Token

  /**
   * Creates a new token.
   *
   * @param {string} type See {@link Token#type type}
   * @param {string | TokenStream} content See {@link Token#content content}
   * @param {string|string[]} [alias] The alias(es) of the token.
   * @param {string} [matchedStr=""] A copy of the full string this token was created from.
   * @class
   * @global
   * @public
   */
  function Token(type, content, alias, matchedStr) {
    /**
     * The type of the token.
     *
     * This is usually the key of a pattern in a {@link Grammar}.
     *
     * @type {string}
     * @see GrammarToken
     * @public
     */
    this.type = type;
    /**
     * The strings or tokens contained by this token.
     *
     * This will be a token stream if the pattern matched also defined an `inside` grammar.
     *
     * @type {string | TokenStream}
     * @public
     */
    this.content = content;
    /**
     * The alias(es) of the token.
     *
     * @type {string|string[]}
     * @see GrammarToken
     * @public
     */
    this.alias = alias;
    // Copy of the full string this token was created from
    this.length = (matchedStr || "").length | 0;
  }

  /**
   * A token stream is an array of strings and {@link Token Token} objects.
   *
   * Token streams have to fulfill a few properties that are assumed by most functions (mostly internal ones) that process
   * them.
   *
   * 1. No adjacent strings.
   * 2. No empty strings.
   *
   *    The only exception here is the token stream that only contains the empty string and nothing else.
   *
   * @typedef {Array<string | Token>} TokenStream
   * @global
   * @public
   */

  /**
   * Converts the given token or token stream to an HTML representation.
   *
   * The following hooks will be run:
   * 1. `wrap`: On each {@link Token}.
   *
   * @param {string | Token | TokenStream} o The token or token stream to be converted.
   * @param {string} language The name of current language.
   * @returns {string} The HTML representation of the token or token stream.
   * @memberof Token
   * @static
   */
  Token.stringify = function stringify(o, language) {
    if (typeof o == "string") {
      return o;
    }
    if (Array.isArray(o)) {
      var s = "";
      o.forEach(function (e) {
        s += stringify(e, language);
      });
      return s;
    }

    var env = {
      type: o.type,
      content: stringify(o.content, language),
      tag: "span",
      classes: ["token", o.type],
      attributes: {},
      language: language,
    };

    var aliases = o.alias;
    if (aliases) {
      if (Array.isArray(aliases)) {
        Array.prototype.push.apply(env.classes, aliases);
      } else {
        env.classes.push(aliases);
      }
    }

    _.hooks.run("wrap", env);

    var attributes = "";
    for (var name in env.attributes) {
      attributes +=
        " " +
        name +
        '="' +
        (env.attributes[name] || "").replace(/"/g, "&quot;") +
        '"';
    }

    return (
      "<" +
      env.tag +
      ' class="' +
      env.classes.join(" ") +
      '"' +
      attributes +
      ">" +
      env.content +
      "</" +
      env.tag +
      ">"
    );
  };

  /**
   * @param {RegExp} pattern
   * @param {number} pos
   * @param {string} text
   * @param {boolean} lookbehind
   * @returns {RegExpExecArray | null}
   */
  function matchPattern(pattern, pos, text, lookbehind) {
    pattern.lastIndex = pos;
    var match = pattern.exec(text);
    if (match && lookbehind && match[1]) {
      // change the match to remove the text matched by the Prism lookbehind group
      var lookbehindLength = match[1].length;
      match.index += lookbehindLength;
      match[0] = match[0].slice(lookbehindLength);
    }
    return match;
  }

  /**
   * @param {string} text
   * @param {LinkedList<string | Token>} tokenList
   * @param {any} grammar
   * @param {LinkedListNode<string | Token>} startNode
   * @param {number} startPos
   * @param {RematchOptions} [rematch]
   * @returns {void}
   * @private
   *
   * @typedef RematchOptions
   * @property {string} cause
   * @property {number} reach
   */
  function matchGrammar(
    text,
    tokenList,
    grammar,
    startNode,
    startPos,
    rematch
  ) {
    for (var token in grammar) {
      if (!grammar.hasOwnProperty(token) || !grammar[token]) {
        continue;
      }

      var patterns = grammar[token];
      patterns = Array.isArray(patterns) ? patterns : [patterns];

      for (var j = 0; j < patterns.length; ++j) {
        if (rematch && rematch.cause == token + "," + j) {
          return;
        }

        var patternObj = patterns[j];
        var inside = patternObj.inside;
        var lookbehind = !!patternObj.lookbehind;
        var greedy = !!patternObj.greedy;
        var alias = patternObj.alias;

        if (greedy && !patternObj.pattern.global) {
          // Without the global flag, lastIndex won't work
          var flags = patternObj.pattern.toString().match(/[imsuy]*$/)[0];
          patternObj.pattern = RegExp(patternObj.pattern.source, flags + "g");
        }

        /** @type {RegExp} */
        var pattern = patternObj.pattern || patternObj;

        for (
          // iterate the token list and keep track of the current token/string position
          var currentNode = startNode.next, pos = startPos;
          currentNode !== tokenList.tail;
          pos += currentNode.value.length, currentNode = currentNode.next
        ) {
          if (rematch && pos >= rematch.reach) {
            break;
          }

          var str = currentNode.value;

          if (tokenList.length > text.length) {
            // Something went terribly wrong, ABORT, ABORT!
            return;
          }

          if (str instanceof Token) {
            continue;
          }

          var removeCount = 1; // this is the to parameter of removeBetween
          var match;

          if (greedy) {
            match = matchPattern(pattern, pos, text, lookbehind);
            if (!match || match.index >= text.length) {
              break;
            }

            var from = match.index;
            var to = match.index + match[0].length;
            var p = pos;

            // find the node that contains the match
            p += currentNode.value.length;
            while (from >= p) {
              currentNode = currentNode.next;
              p += currentNode.value.length;
            }
            // adjust pos (and p)
            p -= currentNode.value.length;
            pos = p;

            // the current node is a Token, then the match starts inside another Token, which is invalid
            if (currentNode.value instanceof Token) {
              continue;
            }

            // find the last node which is affected by this match
            for (
              var k = currentNode;
              k !== tokenList.tail && (p < to || typeof k.value === "string");
              k = k.next
            ) {
              removeCount++;
              p += k.value.length;
            }
            removeCount--;

            // replace with the new match
            str = text.slice(pos, p);
            match.index -= pos;
          } else {
            match = matchPattern(pattern, 0, str, lookbehind);
            if (!match) {
              continue;
            }
          }

          // eslint-disable-next-line no-redeclare
          var from = match.index;
          var matchStr = match[0];
          var before = str.slice(0, from);
          var after = str.slice(from + matchStr.length);

          var reach = pos + str.length;
          if (rematch && reach > rematch.reach) {
            rematch.reach = reach;
          }

          var removeFrom = currentNode.prev;

          if (before) {
            removeFrom = addAfter(tokenList, removeFrom, before);
            pos += before.length;
          }

          removeRange(tokenList, removeFrom, removeCount);

          var wrapped = new Token(
            token,
            inside ? _.tokenize(matchStr, inside) : matchStr,
            alias,
            matchStr
          );
          currentNode = addAfter(tokenList, removeFrom, wrapped);

          if (after) {
            addAfter(tokenList, currentNode, after);
          }

          if (removeCount > 1) {
            // at least one Token object was removed, so we have to do some rematching
            // this can only happen if the current pattern is greedy

            /** @type {RematchOptions} */
            var nestedRematch = {
              cause: token + "," + j,
              reach: reach,
            };
            matchGrammar(
              text,
              tokenList,
              grammar,
              currentNode.prev,
              pos,
              nestedRematch
            );

            // the reach might have been extended because of the rematching
            if (rematch && nestedRematch.reach > rematch.reach) {
              rematch.reach = nestedRematch.reach;
            }
          }
        }
      }
    }
  }

  /**
   * @typedef LinkedListNode
   * @property {T} value
   * @property {LinkedListNode<T> | null} prev The previous node.
   * @property {LinkedListNode<T> | null} next The next node.
   * @template T
   * @private
   */

  /**
   * @template T
   * @private
   */
  function LinkedList() {
    /** @type {LinkedListNode<T>} */
    var head = { value: null, prev: null, next: null };
    /** @type {LinkedListNode<T>} */
    var tail = { value: null, prev: head, next: null };
    head.next = tail;

    /** @type {LinkedListNode<T>} */
    this.head = head;
    /** @type {LinkedListNode<T>} */
    this.tail = tail;
    this.length = 0;
  }

  /**
   * Adds a new node with the given value to the list.
   *
   * @param {LinkedList<T>} list
   * @param {LinkedListNode<T>} node
   * @param {T} value
   * @returns {LinkedListNode<T>} The added node.
   * @template T
   */
  function addAfter(list, node, value) {
    // assumes that node != list.tail && values.length >= 0
    var next = node.next;

    var newNode = { value: value, prev: node, next: next };
    node.next = newNode;
    next.prev = newNode;
    list.length++;

    return newNode;
  }
  /**
   * Removes `count` nodes after the given node. The given node will not be removed.
   *
   * @param {LinkedList<T>} list
   * @param {LinkedListNode<T>} node
   * @param {number} count
   * @template T
   */
  function removeRange(list, node, count) {
    var next = node.next;
    for (var i = 0; i < count && next !== list.tail; i++) {
      next = next.next;
    }
    node.next = next;
    next.prev = node;
    list.length -= i;
  }
  /**
   * @param {LinkedList<T>} list
   * @returns {T[]}
   * @template T
   */
  function toArray(list) {
    var array = [];
    var node = list.head.next;
    while (node !== list.tail) {
      array.push(node.value);
      node = node.next;
    }
    return array;
  }

  if (!_self.document) {
    if (!_self.addEventListener) {
      // in Node.js
      return _;
    }

    if (!_.disableWorkerMessageHandler) {
      // In worker
      _self.addEventListener(
        "message",
        function (evt) {
          var message = JSON.parse(evt.data);
          var lang = message.language;
          var code = message.code;
          var immediateClose = message.immediateClose;

          _self.postMessage(_.highlight(code, _.languages[lang], lang));
          if (immediateClose) {
            _self.close();
          }
        },
        false
      );
    }

    return _;
  }

  // Get current script and highlight
  var script = _.util.currentScript();

  if (script) {
    _.filename = script.src;

    if (script.hasAttribute("data-manual")) {
      _.manual = true;
    }
  }

  function highlightAutomaticallyCallback() {
    if (!_.manual) {
      _.highlightAll();
    }
  }

  if (!_.manual) {
    // If the document state is "loading", then we'll use DOMContentLoaded.
    // If the document state is "interactive" and the prism.js script is deferred, then we'll also use the
    // DOMContentLoaded event because there might be some plugins or languages which have also been deferred and they
    // might take longer one animation frame to execute which can create a race condition where only some plugins have
    // been loaded when Prism.highlightAll() is executed, depending on how fast resources are loaded.
    // See https://github.com/PrismJS/prism/issues/2102
    var readyState = document.readyState;
    if (
      readyState === "loading" ||
      (readyState === "interactive" && script && script.defer)
    ) {
      document.addEventListener(
        "DOMContentLoaded",
        highlightAutomaticallyCallback
      );
    } else {
      if (window.requestAnimationFrame) {
        window.requestAnimationFrame(highlightAutomaticallyCallback);
      } else {
        window.setTimeout(highlightAutomaticallyCallback, 16);
      }
    }
  }

  return _;
})(_self);

if (typeof module !== "undefined" && module.exports) {
  module.exports = Prism;
}

// hack for components to work correctly in node.js
if (typeof global !== "undefined") {
  global.Prism = Prism;
}

// some additional documentation/types

/**
 * The expansion of a simple `RegExp` literal to support additional properties.
 *
 * @typedef GrammarToken
 * @property {RegExp} pattern The regular expression of the token.
 * @property {boolean} [lookbehind=false] If `true`, then the first capturing group of `pattern` will (effectively)
 * behave as a lookbehind group meaning that the captured text will not be part of the matched text of the new token.
 * @property {boolean} [greedy=false] Whether the token is greedy.
 * @property {string|string[]} [alias] An optional alias or list of aliases.
 * @property {Grammar} [inside] The nested grammar of this token.
 *
 * The `inside` grammar will be used to tokenize the text value of each token of this kind.
 *
 * This can be used to make nested and even recursive language definitions.
 *
 * Note: This can cause infinite recursion. Be careful when you embed different languages or even the same language into
 * each another.
 * @global
 * @public
 */

/**
 * @typedef Grammar
 * @type {Object<string, RegExp | GrammarToken | Array<RegExp | GrammarToken>>}
 * @property {Grammar} [rest] An optional grammar object that will be appended to this grammar.
 * @global
 * @public
 */

/**
 * A function which will invoked after an element was successfully highlighted.
 *
 * @callback HighlightCallback
 * @param {Element} element The element successfully highlighted.
 * @returns {void}
 * @global
 * @public
 */

/**
 * @callback HookCallback
 * @param {Object<string, any>} env The environment variables of the hook.
 * @returns {void}
 * @global
 * @public
 */
Prism.languages.markup = {
  comment: {
    pattern: /<!--(?:(?!<!--)[\s\S])*?-->/,
    greedy: true,
  },
  prolog: {
    pattern: /<\?[\s\S]+?\?>/,
    greedy: true,
  },
  doctype: {
    // https://www.w3.org/TR/xml/#NT-doctypedecl
    pattern:
      /<!DOCTYPE(?:[^>"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|<!--(?:[^-]|-(?!->))*-->)*\]\s*)?>/i,
    greedy: true,
    inside: {
      "internal-subset": {
        pattern: /(^[^\[]*\[)[\s\S]+(?=\]>$)/,
        lookbehind: true,
        greedy: true,
        inside: null, // see below
      },
      string: {
        pattern: /"[^"]*"|'[^']*'/,
        greedy: true,
      },
      punctuation: /^<!|>$|[[\]]/,
      "doctype-tag": /^DOCTYPE/i,
      name: /[^\s<>'"]+/,
    },
  },
  cdata: {
    pattern: /<!\[CDATA\[[\s\S]*?\]\]>/i,
    greedy: true,
  },
  tag: {
    pattern:
      /<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,
    greedy: true,
    inside: {
      tag: {
        pattern: /^<\/?[^\s>\/]+/,
        inside: {
          punctuation: /^<\/?/,
          namespace: /^[^\s>\/:]+:/,
        },
      },
      "special-attr": [],
      "attr-value": {
        pattern: /=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,
        inside: {
          punctuation: [
            {
              pattern: /^=/,
              alias: "attr-equals",
            },
            /"|'/,
          ],
        },
      },
      punctuation: /\/?>/,
      "attr-name": {
        pattern: /[^\s>\/]+/,
        inside: {
          namespace: /^[^\s>\/:]+:/,
        },
      },
    },
  },
  entity: [
    {
      pattern: /&[\da-z]{1,8};/i,
      alias: "named-entity",
    },
    /&#x?[\da-f]{1,8};/i,
  ],
};

Prism.languages.markup["tag"].inside["attr-value"].inside["entity"] =
  Prism.languages.markup["entity"];
Prism.languages.markup["doctype"].inside["internal-subset"].inside =
  Prism.languages.markup;

// Plugin to make entity title show the real entity, idea by Roman Komarov
Prism.hooks.add("wrap", function (env) {
  if (env.type === "entity") {
    env.attributes["title"] = env.content.replace(/&amp;/, "&");
  }
});

Object.defineProperty(Prism.languages.markup.tag, "addInlined", {
  /**
   * Adds an inlined language to markup.
   *
   * An example of an inlined language is CSS with `<style>` tags.
   *
   * @param {string} tagName The name of the tag that contains the inlined language. This name will be treated as
   * case insensitive.
   * @param {string} lang The language key.
   * @example
   * addInlined('style', 'css');
   */
  value: function addInlined(tagName, lang) {
    var includedCdataInside = {};
    includedCdataInside["language-" + lang] = {
      pattern: /(^<!\[CDATA\[)[\s\S]+?(?=\]\]>$)/i,
      lookbehind: true,
      inside: Prism.languages[lang],
    };
    includedCdataInside["cdata"] = /^<!\[CDATA\[|\]\]>$/i;

    var inside = {
      "included-cdata": {
        pattern: /<!\[CDATA\[[\s\S]*?\]\]>/i,
        inside: includedCdataInside,
      },
    };
    inside["language-" + lang] = {
      pattern: /[\s\S]+/,
      inside: Prism.languages[lang],
    };

    var def = {};
    def[tagName] = {
      pattern: RegExp(
        /(<__[^>]*>)(?:<!\[CDATA\[(?:[^\]]|\](?!\]>))*\]\]>|(?!<!\[CDATA\[)[\s\S])*?(?=<\/__>)/.source.replace(
          /__/g,
          function () {
            return tagName;
          }
        ),
        "i"
      ),
      lookbehind: true,
      greedy: true,
      inside: inside,
    };

    Prism.languages.insertBefore("markup", "cdata", def);
  },
});
Object.defineProperty(Prism.languages.markup.tag, "addAttribute", {
  /**
   * Adds an pattern to highlight languages embedded in HTML attributes.
   *
   * An example of an inlined language is CSS with `style` attributes.
   *
   * @param {string} attrName The name of the tag that contains the inlined language. This name will be treated as
   * case insensitive.
   * @param {string} lang The language key.
   * @example
   * addAttribute('style', 'css');
   */
  value: function (attrName, lang) {
    Prism.languages.markup.tag.inside["special-attr"].push({
      pattern: RegExp(
        /(^|["'\s])/.source +
          "(?:" +
          attrName +
          ")" +
          /\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,
        "i"
      ),
      lookbehind: true,
      inside: {
        "attr-name": /^[^\s=]+/,
        "attr-value": {
          pattern: /=[\s\S]+/,
          inside: {
            value: {
              pattern: /(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,
              lookbehind: true,
              alias: [lang, "language-" + lang],
              inside: Prism.languages[lang],
            },
            punctuation: [
              {
                pattern: /^=/,
                alias: "attr-equals",
              },
              /"|'/,
            ],
          },
        },
      },
    });
  },
});

Prism.languages.html = Prism.languages.markup;
Prism.languages.mathml = Prism.languages.markup;
Prism.languages.svg = Prism.languages.markup;

Prism.languages.xml = Prism.languages.extend("markup", {});
Prism.languages.ssml = Prism.languages.xml;
Prism.languages.atom = Prism.languages.xml;
Prism.languages.rss = Prism.languages.xml;

(function (Prism) {
  var string =
    /(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;

  Prism.languages.css = {
    comment: /\/\*[\s\S]*?\*\//,
    atrule: {
      pattern: /@[\w-](?:[^;{\s]|\s+(?![\s{]))*(?:;|(?=\s*\{))/,
      inside: {
        rule: /^@[\w-]+/,
        "selector-function-argument": {
          pattern:
            /(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,
          lookbehind: true,
          alias: "selector",
        },
        keyword: {
          pattern: /(^|[^\w-])(?:and|not|only|or)(?![\w-])/,
          lookbehind: true,
        },
        // See rest below
      },
    },
    url: {
      // https://drafts.csswg.org/css-values-3/#urls
      pattern: RegExp(
        "\\burl\\((?:" +
          string.source +
          "|" +
          /(?:[^\\\r\n()"']|\\[\s\S])*/.source +
          ")\\)",
        "i"
      ),
      greedy: true,
      inside: {
        function: /^url/i,
        punctuation: /^\(|\)$/,
        string: {
          pattern: RegExp("^" + string.source + "$"),
          alias: "url",
        },
      },
    },
    selector: {
      pattern: RegExp(
        "(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|" +
          string.source +
          ")*(?=\\s*\\{)"
      ),
      lookbehind: true,
    },
    string: {
      pattern: string,
      greedy: true,
    },
    property: {
      pattern:
        /(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,
      lookbehind: true,
    },
    important: /!important\b/i,
    function: {
      pattern: /(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,
      lookbehind: true,
    },
    punctuation: /[(){};:,]/,
  };

  Prism.languages.css["atrule"].inside.rest = Prism.languages.css;

  var markup = Prism.languages.markup;
  if (markup) {
    markup.tag.addInlined("style", "css");
    markup.tag.addAttribute("style", "css");
  }
})(Prism);

Prism.languages.clike = {
  comment: [
    {
      pattern: /(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,
      lookbehind: true,
      greedy: true,
    },
    {
      pattern: /(^|[^\\:])\/\/.*/,
      lookbehind: true,
      greedy: true,
    },
  ],
  string: {
    pattern: /(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
    greedy: true,
  },
  "class-name": {
    pattern:
      /(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,
    lookbehind: true,
    inside: {
      punctuation: /[.\\]/,
    },
  },
  keyword:
    /\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,
  boolean: /\b(?:false|true)\b/,
  function: /\b\w+(?=\()/,
  number: /\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,
  operator: /[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,
  punctuation: /[{}[\];(),.:]/,
};

Prism.languages.javascript = Prism.languages.extend("clike", {
  "class-name": [
    Prism.languages.clike["class-name"],
    {
      pattern:
        /(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,
      lookbehind: true,
    },
  ],
  keyword: [
    {
      pattern: /((?:^|\})\s*)catch\b/,
      lookbehind: true,
    },
    {
      pattern:
        /(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,
      lookbehind: true,
    },
  ],
  // Allow for all non-ASCII characters (See http://stackoverflow.com/a/2008444)
  function:
    /#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,
  number: {
    pattern: RegExp(
      /(^|[^\w$])/.source +
        "(?:" +
        // constant
        (/NaN|Infinity/.source +
          "|" +
          // binary integer
          /0[bB][01]+(?:_[01]+)*n?/.source +
          "|" +
          // octal integer
          /0[oO][0-7]+(?:_[0-7]+)*n?/.source +
          "|" +
          // hexadecimal integer
          /0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source +
          "|" +
          // decimal bigint
          /\d+(?:_\d+)*n/.source +
          "|" +
          // decimal number (integer or float) but no bigint
          /(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/
            .source) +
        ")" +
        /(?![\w$])/.source
    ),
    lookbehind: true,
  },
  operator:
    /--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/,
});

Prism.languages.javascript["class-name"][0].pattern =
  /(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/;

Prism.languages.insertBefore("javascript", "keyword", {
  regex: {
    // eslint-disable-next-line regexp/no-dupe-characters-character-class
    pattern:
      /((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,
    lookbehind: true,
    greedy: true,
    inside: {
      "regex-source": {
        pattern: /^(\/)[\s\S]+(?=\/[a-z]*$)/,
        lookbehind: true,
        alias: "language-regex",
        inside: Prism.languages.regex,
      },
      "regex-delimiter": /^\/|\/$/,
      "regex-flags": /^[a-z]+$/,
    },
  },
  // This must be declared before keyword because we use "function" inside the look-forward
  "function-variable": {
    pattern:
      /#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,
    alias: "function",
  },
  parameter: [
    {
      pattern:
        /(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,
      lookbehind: true,
      inside: Prism.languages.javascript,
    },
    {
      pattern:
        /(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,
      lookbehind: true,
      inside: Prism.languages.javascript,
    },
    {
      pattern:
        /(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,
      lookbehind: true,
      inside: Prism.languages.javascript,
    },
    {
      pattern:
        /((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,
      lookbehind: true,
      inside: Prism.languages.javascript,
    },
  ],
  constant: /\b[A-Z](?:[A-Z_]|\dx?)*\b/,
});

Prism.languages.insertBefore("javascript", "string", {
  hashbang: {
    pattern: /^#!.*/,
    greedy: true,
    alias: "comment",
  },
  "template-string": {
    pattern:
      /`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,
    greedy: true,
    inside: {
      "template-punctuation": {
        pattern: /^`|`$/,
        alias: "string",
      },
      interpolation: {
        pattern:
          /((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,
        lookbehind: true,
        inside: {
          "interpolation-punctuation": {
            pattern: /^\$\{|\}$/,
            alias: "punctuation",
          },
          rest: Prism.languages.javascript,
        },
      },
      string: /[\s\S]+/,
    },
  },
  "string-property": {
    pattern:
      /((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,
    lookbehind: true,
    greedy: true,
    alias: "property",
  },
});

Prism.languages.insertBefore("javascript", "operator", {
  "literal-property": {
    pattern:
      /((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,
    lookbehind: true,
    alias: "property",
  },
});

if (Prism.languages.markup) {
  Prism.languages.markup.tag.addInlined("script", "javascript");

  // add attribute support for all DOM events.
  // https://developer.mozilla.org/en-US/docs/Web/Events#Standard_events
  Prism.languages.markup.tag.addAttribute(
    /on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/
      .source,
    "javascript"
  );
}

Prism.languages.js = Prism.languages.javascript;

Prism.languages.python = {
  comment: {
    pattern: /(^|[^\\])#.*/,
    lookbehind: true,
    greedy: true,
  },
  "string-interpolation": {
    pattern:
      /(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,
    greedy: true,
    inside: {
      interpolation: {
        // "{" <expression> <optional "!s", "!r", or "!a"> <optional ":" format specifier> "}"
        pattern:
          /((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,
        lookbehind: true,
        inside: {
          "format-spec": {
            pattern: /(:)[^:(){}]+(?=\}$)/,
            lookbehind: true,
          },
          "conversion-option": {
            pattern: /![sra](?=[:}]$)/,
            alias: "punctuation",
          },
          rest: null,
        },
      },
      string: /[\s\S]+/,
    },
  },
  "triple-quoted-string": {
    pattern: /(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,
    greedy: true,
    alias: "string",
  },
  string: {
    pattern: /(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,
    greedy: true,
  },
  function: {
    pattern: /((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,
    lookbehind: true,
  },
  "class-name": {
    pattern: /(\bclass\s+)\w+/i,
    lookbehind: true,
  },
  decorator: {
    pattern: /(^[\t ]*)@\w+(?:\.\w+)*/m,
    lookbehind: true,
    alias: ["annotation", "punctuation"],
    inside: {
      punctuation: /\./,
    },
  },
  keyword:
    /\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,
  builtin:
    /\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,
  boolean: /\b(?:False|None|True)\b/,
  number:
    /\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,
  operator: /[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,
  punctuation: /[{}[\];(),.:]/,
};

Prism.languages.python["string-interpolation"].inside[
  "interpolation"
].inside.rest = Prism.languages.python;

Prism.languages.py = Prism.languages.python;

(function () {
  if (typeof Prism === "undefined") {
    return;
  }

  var assign =
    Object.assign ||
    function (obj1, obj2) {
      for (var name in obj2) {
        if (obj2.hasOwnProperty(name)) {
          obj1[name] = obj2[name];
        }
      }
      return obj1;
    };

  function NormalizeWhitespace(defaults) {
    this.defaults = assign({}, defaults);
  }

  function toCamelCase(value) {
    return value.replace(/-(\w)/g, function (match, firstChar) {
      return firstChar.toUpperCase();
    });
  }

  function tabLen(str) {
    var res = 0;
    for (var i = 0; i < str.length; ++i) {
      if (str.charCodeAt(i) == "\t".charCodeAt(0)) {
        res += 3;
      }
    }
    return str.length + res;
  }

  NormalizeWhitespace.prototype = {
    setDefaults: function (defaults) {
      this.defaults = assign(this.defaults, defaults);
    },
    normalize: function (input, settings) {
      settings = assign(this.defaults, settings);

      for (var name in settings) {
        var methodName = toCamelCase(name);
        if (
          name !== "normalize" &&
          methodName !== "setDefaults" &&
          settings[name] &&
          this[methodName]
        ) {
          input = this[methodName].call(this, input, settings[name]);
        }
      }

      return input;
    },

    /*
     * Normalization methods
     */
    leftTrim: function (input) {
      return input.replace(/^\s+/, "");
    },
    rightTrim: function (input) {
      return input.replace(/\s+$/, "");
    },
    tabsToSpaces: function (input, spaces) {
      spaces = spaces | 0 || 4;
      return input.replace(/\t/g, new Array(++spaces).join(" "));
    },
    spacesToTabs: function (input, spaces) {
      spaces = spaces | 0 || 4;
      return input.replace(RegExp(" {" + spaces + "}", "g"), "\t");
    },
    removeTrailing: function (input) {
      return input.replace(/\s*?$/gm, "");
    },
    // Support for deprecated plugin remove-initial-line-feed
    removeInitialLineFeed: function (input) {
      return input.replace(/^(?:\r?\n|\r)/, "");
    },
    removeIndent: function (input) {
      var indents = input.match(/^[^\S\n\r]*(?=\S)/gm);

      if (!indents || !indents[0].length) {
        return input;
      }

      indents.sort(function (a, b) {
        return a.length - b.length;
      });

      if (!indents[0].length) {
        return input;
      }

      return input.replace(RegExp("^" + indents[0], "gm"), "");
    },
    indent: function (input, tabs) {
      return input.replace(
        /^[^\S\n\r]*(?=\S)/gm,
        new Array(++tabs).join("\t") + "$&"
      );
    },
    breakLines: function (input, characters) {
      characters = characters === true ? 80 : characters | 0 || 80;

      var lines = input.split("\n");
      for (var i = 0; i < lines.length; ++i) {
        if (tabLen(lines[i]) <= characters) {
          continue;
        }

        var line = lines[i].split(/(\s+)/g);
        var len = 0;

        for (var j = 0; j < line.length; ++j) {
          var tl = tabLen(line[j]);
          len += tl;
          if (len > characters) {
            line[j] = "\n" + line[j];
            len = tl;
          }
        }
        lines[i] = line.join("");
      }
      return lines.join("\n");
    },
  };

  // Support node modules
  if (typeof module !== "undefined" && module.exports) {
    module.exports = NormalizeWhitespace;
  }

  Prism.plugins.NormalizeWhitespace = new NormalizeWhitespace({
    "remove-trailing": true,
    "remove-indent": false,
    "left-trim": false,
    "right-trim": true,
    /*'break-lines': 80,
		'indent': 2,
		'remove-initial-line-feed': false,
		'tabs-to-spaces': 4,
		'spaces-to-tabs': 4*/
  });

  Prism.hooks.add("before-sanity-check", function (env) {
    var Normalizer = Prism.plugins.NormalizeWhitespace;

    // Check settings
    if (env.settings && env.settings["whitespace-normalization"] === false) {
      return;
    }

    // Check classes
    if (!Prism.util.isActive(env.element, "whitespace-normalization", true)) {
      return;
    }

    // Simple mode if there is no env.element
    if ((!env.element || !env.element.parentNode) && env.code) {
      env.code = Normalizer.normalize(env.code, env.settings);
      return;
    }

    // Normal mode
    var pre = env.element.parentNode;
    if (!env.code || !pre || pre.nodeName.toLowerCase() !== "pre") {
      return;
    }

    var children = pre.childNodes;
    var before = "";
    var after = "";
    var codeFound = false;

    // Move surrounding whitespace from the <pre> tag into the <code> tag
    for (var i = 0; i < children.length; ++i) {
      var node = children[i];

      if (node == env.element) {
        codeFound = true;
      } else if (node.nodeName === "#text") {
        if (codeFound) {
          after += node.nodeValue;
        } else {
          before += node.nodeValue;
        }

        pre.removeChild(node);
        --i;
      }
    }

    if (!env.element.children.length || !Prism.plugins.KeepMarkup) {
      env.code = before + env.code + after;
      env.code = Normalizer.normalize(env.code, env.settings);
    } else {
      // Preserve markup for keep-markup plugin
      var html = before + env.element.innerHTML + after;
      env.element.innerHTML = Normalizer.normalize(html, env.settings);
      env.code = env.element.textContent;
    }
  });
})();
      
</script>
		       <script>
(function () {
  function Tablesort(el, options) {
    if (!(this instanceof Tablesort)) return new Tablesort(el, options);

    if (!el || el.tagName !== "TABLE") {
      throw new Error("Element must be a table");
    }
    this.init(el, options || {});
  }

  var sortOptions = [];

  var createEvent = function (name) {
    var evt;

    if (!window.CustomEvent || typeof window.CustomEvent !== "function") {
      evt = document.createEvent("CustomEvent");
      evt.initCustomEvent(name, false, false, undefined);
    } else {
      evt = new CustomEvent(name);
    }

    return evt;
  };

  var getInnerText = function (el, options) {
    return (
      el.getAttribute(options.sortAttribute || "data-sort") ||
      el.textContent ||
      el.innerText ||
      ""
    );
  };

  // Default sort method if no better sort method is found
  var caseInsensitiveSort = function (a, b) {
    a = a.trim().toLowerCase();
    b = b.trim().toLowerCase();

    if (a === b) return 0;
    if (a < b) return 1;

    return -1;
  };

  var getCellByKey = function (cells, key) {
    return [].slice.call(cells).find(function (cell) {
      return cell.getAttribute("data-sort-column-key") === key;
    });
  };

  // Stable sort function
  // If two elements are equal under the original sort function,
  // then there relative order is reversed
  var stabilize = function (sort, antiStabilize) {
    return function (a, b) {
      var unstableResult = sort(a.td, b.td);

      if (unstableResult === 0) {
        if (antiStabilize) return b.index - a.index;
        return a.index - b.index;
      }

      return unstableResult;
    };
  };

  Tablesort.extend = function (name, pattern, sort) {
    if (typeof pattern !== "function" || typeof sort !== "function") {
      throw new Error("Pattern and sort must be a function");
    }

    sortOptions.push({
      name: name,
      pattern: pattern,
      sort: sort,
    });
  };

  Tablesort.prototype = {
    init: function (el, options) {
      var that = this,
        firstRow,
        defaultSort,
        i,
        cell;

      that.table = el;
      that.thead = false;
      that.options = options;

      if (el.rows && el.rows.length > 0) {
        if (el.tHead && el.tHead.rows.length > 0) {
          for (i = 0; i < el.tHead.rows.length; i++) {
            if (el.tHead.rows[i].getAttribute("data-sort-method") === "thead") {
              firstRow = el.tHead.rows[i];
              break;
            }
          }
          if (!firstRow) {
            firstRow = el.tHead.rows[el.tHead.rows.length - 1];
          }
          that.thead = true;
        } else {
          firstRow = el.rows[0];
        }
      }

      if (!firstRow) return;

      var onClick = function () {
        if (that.current && that.current !== this) {
          that.current.removeAttribute("aria-sort");
        }

        that.current = this;
        that.sortTable(this);
      };

      // Assume first row is the header and attach a click handler to each.
      for (i = 0; i < firstRow.cells.length; i++) {
        cell = firstRow.cells[i];
        cell.setAttribute("role", "columnheader");
        if (cell.getAttribute("data-sort-method") !== "none") {
          cell.tabindex = 0;
          cell.addEventListener("click", onClick, false);

          if (cell.getAttribute("data-sort-default") !== null) {
            defaultSort = cell;
          }
        }
      }

      if (defaultSort) {
        that.current = defaultSort;
        that.sortTable(defaultSort);
      }
    },

    sortTable: function (header, update) {
      var that = this,
        columnKey = header.getAttribute("data-sort-column-key"),
        column = header.cellIndex,
        sortFunction = caseInsensitiveSort,
        item = "",
        items = [],
        i = that.thead ? 0 : 1,
        sortMethod = header.getAttribute("data-sort-method"),
        sortOrder = header.getAttribute("aria-sort");

      that.table.dispatchEvent(createEvent("beforeSort"));

      // If updating an existing sort, direction should remain unchanged.
      if (!update) {
        if (sortOrder === "ascending") {
          sortOrder = "descending";
        } else if (sortOrder === "descending") {
          sortOrder = "ascending";
        } else {
          sortOrder = that.options.descending ? "descending" : "ascending";
        }

        header.setAttribute("aria-sort", sortOrder);
      }

      if (that.table.rows.length < 2) return;

      // If we force a sort method, it is not necessary to check rows
      if (!sortMethod) {
        var cell;
        while (items.length < 3 && i < that.table.tBodies[0].rows.length) {
          if (columnKey) {
            cell = getCellByKey(that.table.tBodies[0].rows[i].cells, columnKey);
          } else {
            cell = that.table.tBodies[0].rows[i].cells[column];
          }

          // Treat missing cells as empty cells
          item = cell ? getInnerText(cell, that.options) : "";

          item = item.trim();

          if (item.length > 0) {
            items.push(item);
          }

          i++;
        }

        if (!items) return;
      }

      for (i = 0; i < sortOptions.length; i++) {
        item = sortOptions[i];

        if (sortMethod) {
          if (item.name === sortMethod) {
            sortFunction = item.sort;
            break;
          }
        } else if (items.every(item.pattern)) {
          sortFunction = item.sort;
          break;
        }
      }

      that.col = column;

      for (i = 0; i < that.table.tBodies.length; i++) {
        var newRows = [],
          noSorts = {},
          j,
          totalRows = 0,
          noSortsSoFar = 0;

        if (that.table.tBodies[i].rows.length < 2) continue;

        for (j = 0; j < that.table.tBodies[i].rows.length; j++) {
          var cell;

          item = that.table.tBodies[i].rows[j];
          if (item.getAttribute("data-sort-method") === "none") {
            // keep no-sorts in separate list to be able to insert
            // them back at their original position later
            noSorts[totalRows] = item;
          } else {
            if (columnKey) {
              cell = getCellByKey(item.cells, columnKey);
            } else {
              cell = item.cells[that.col];
            }
            // Save the index for stable sorting
            newRows.push({
              tr: item,
              td: cell ? getInnerText(cell, that.options) : "",
              index: totalRows,
            });
          }
          totalRows++;
        }
        // Before we append should we reverse the new array or not?
        // If we reverse, the sort needs to be `anti-stable` so that
        // the double negatives cancel out
        if (sortOrder === "descending") {
          newRows.sort(stabilize(sortFunction, true));
        } else {
          newRows.sort(stabilize(sortFunction, false));
          newRows.reverse();
        }

        // append rows that already exist rather than creating new ones
        for (j = 0; j < totalRows; j++) {
          if (noSorts[j]) {
            // We have a no-sort row for this position, insert it here.
            item = noSorts[j];
            noSortsSoFar++;
          } else {
            item = newRows[j - noSortsSoFar].tr;
          }

          // appendChild(x) moves x if already present somewhere else in the DOM
          that.table.tBodies[i].appendChild(item);
        }
      }

      that.table.dispatchEvent(createEvent("afterSort"));
    },

    refresh: function () {
      if (this.current !== undefined) {
        this.sortTable(this.current, true);
      }
    },
  };

  if (typeof module !== "undefined" && module.exports) {
    module.exports = Tablesort;
  } else {
    window.Tablesort = Tablesort;
  }
})();
</script>
		       <script>
(function () {
  var cleanNumber = function (i) {
      return i.replace(/[^\-?0-9.]/g, "");
    },
    compareNumber = function (a, b) {
      a = parseFloat(a);
      b = parseFloat(b);

      a = isNaN(a) ? 0 : a;
      b = isNaN(b) ? 0 : b;

      return a - b;
    };

  Tablesort.extend(
    "number",
    function (item) {
      return (
        item.match(/^[-+]?[£\x24Û¢´€]?\d+\s*([,\.]\d{0,2})/) || // Prefixed currency
        item.match(/^[-+]?\d+\s*([,\.]\d{0,2})?[£\x24Û¢´€]/) || // Suffixed currency
        item.match(/^[-+]?(\d)*-?([,\.]){0,1}-?(\d)+([E,e][\-+][\d]+)?%?$/)
      ); // Number
    },
    function (a, b) {
      a = cleanNumber(a);
      b = cleanNumber(b);

      return compareNumber(b, a);
    }
  );
})();
			 
		       </script>
    <script>
      const profile = {
    "alloc_samples": 383,
    "args": [
        "test_new.py"
    ],
    "elapsed_time_sec": 10.265758991241455,
    "entrypoint_dir": "/Users/xclin/python_thread",
    "filename": "/Users/xclin/python_thread",
    "files": {
        "/Users/xclin/python_thread/test_new.py": {
            "functions": [
                {
                    "line": "cpu_intensive_task",
                    "lineno": 4,
                    "memory_samples": [
                        [
                            7904658833,
                            1540.6874551773071
                        ],
                        [
                            7938303875,
                            1556.0007486343384
                        ],
                        [
                            1514325250,
                            320.4333305358887
                        ],
                        [
                            4651195375,
                            938.8812103271484
                        ]
                    ],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 5.702653698707739,
                    "n_core_utilization": 0.3805454604660114,
                    "n_cpu_percent_c": 2.943202919946794,
                    "n_cpu_percent_python": 0.29675716289733867,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 32.73609733581543,
                    "n_malloc_mb": 65.22116470336914,
                    "n_mallocs": 0,
                    "n_peak_mb": 32.73609733581543,
                    "n_python_fraction": 0.30374785211344607,
                    "n_sys_percent": 0.23839973520320762,
                    "n_usage_fraction": 0.034887771885270966
                },
                {
                    "line": "memory_intensive_task",
                    "lineno": 11,
                    "memory_samples": [
                        [
                            1586911500,
                            330.52758407592773
                        ],
                        [
                            1586926083,
                            340.68763256073
                        ],
                        [
                            1628119958,
                            351.0104064941406
                        ],
                        [
                            1628134583,
                            361.01042461395264
                        ],
                        [
                            1699588583,
                            355.8333511352539
                        ],
                        [
                            1699601458,
                            365.83337688446045
                        ],
                        [
                            1699608666,
                            375.833402633667
                        ],
                        [
                            1699616000,
                            387.03852939605713
                        ],
                        [
                            1723735291,
                            397.41551971435547
                        ],
                        [
                            1739026000,
                            407.50978088378906
                        ],
                        [
                            1767452708,
                            419.01417541503906
                        ],
                        [
                            1797145125,
                            432.32678985595703
                        ],
                        [
                            1822594791,
                            442.4210433959961
                        ],
                        [
                            1834565541,
                            452.5153121948242
                        ],
                        [
                            1850294125,
                            464.1138000488281
                        ],
                        [
                            1869758250,
                            474.2080535888672
                        ],
                        [
                            1883884333,
                            484.3023147583008
                        ],
                        [
                            1903065791,
                            494.3965759277344
                        ],
                        [
                            1916763375,
                            504.49083709716797
                        ],
                        [
                            1936522083,
                            514.5851058959961
                        ],
                        [
                            1956721000,
                            528.3486099243164
                        ],
                        [
                            1975292166,
                            538.44287109375
                        ],
                        [
                            2001179708,
                            555.3200836181641
                        ],
                        [
                            2020334375,
                            565.4143447875977
                        ],
                        [
                            2039004750,
                            575.5086135864258
                        ],
                        [
                            2053672583,
                            585.6590805053711
                        ],
                        [
                            2070966625,
                            595.7533493041992
                        ],
                        [
                            2092377500,
                            605.8476104736328
                        ],
                        [
                            2108046083,
                            619.7749938964844
                        ],
                        [
                            4710785583,
                            933.5699081420898
                        ],
                        [
                            4720401708,
                            943.9127807617188
                        ],
                        [
                            4740086708,
                            954.0070343017578
                        ],
                        [
                            4764107375,
                            964.9048156738281
                        ],
                        [
                            4789696916,
                            975.920166015625
                        ],
                        [
                            4802466750,
                            986.0144195556641
                        ],
                        [
                            4842719375,
                            998.139533996582
                        ],
                        [
                            4842724416,
                            1008.1395444869995
                        ],
                        [
                            4860954000,
                            1018.3280487060547
                        ],
                        [
                            4947300750,
                            1029.8319778442383
                        ],
                        [
                            4947305000,
                            1043.0501890182495
                        ],
                        [
                            4947307208,
                            1053.050199508667
                        ],
                        [
                            4947309791,
                            1063.0502099990845
                        ],
                        [
                            4960439375,
                            1074.9309539794922
                        ],
                        [
                            4983162375,
                            1085.0252151489258
                        ],
                        [
                            4994524916,
                            1095.1194763183594
                        ],
                        [
                            5012238333,
                            1105.2137298583984
                        ],
                        [
                            5025768458,
                            1115.307991027832
                        ],
                        [
                            5042824291,
                            1125.4022521972656
                        ],
                        [
                            5064472000,
                            1139.1659317016602
                        ],
                        [
                            5084109083,
                            1149.2601928710938
                        ],
                        [
                            5104852875,
                            1166.1375198364258
                        ],
                        [
                            5123068916,
                            1176.2317810058594
                        ],
                        [
                            5142381125,
                            1186.3260345458984
                        ],
                        [
                            5152115333,
                            1196.4767532348633
                        ],
                        [
                            5171178041,
                            1206.5710144042969
                        ],
                        [
                            5191111333,
                            1216.665283203125
                        ],
                        [
                            5208898958,
                            1230.5928344726562
                        ],
                        [
                            7974245750,
                            1551.1085367202759
                        ],
                        [
                            8078905291,
                            1562.0294351577759
                        ],
                        [
                            8078910166,
                            1572.0294609069824
                        ],
                        [
                            8078912625,
                            1582.029486656189
                        ],
                        [
                            8078915000,
                            1592.0295133590698
                        ],
                        [
                            8078917166,
                            1602.0295238494873
                        ],
                        [
                            8185784375,
                            1612.5007495880127
                        ],
                        [
                            8185799083,
                            1622.5007753372192
                        ],
                        [
                            8185810708,
                            1632.5007934570312
                        ],
                        [
                            8185817208,
                            1642.5008192062378
                        ],
                        [
                            8185823583,
                            1652.5008449554443
                        ],
                        [
                            8185829875,
                            1662.5008554458618
                        ],
                        [
                            8204504416,
                            1673.0663242340088
                        ],
                        [
                            8215791208,
                            1684.3921070098877
                        ],
                        [
                            8234073750,
                            1694.4863681793213
                        ],
                        [
                            8249107583,
                            1704.5806293487549
                        ],
                        [
                            8267385958,
                            1714.674882888794
                        ],
                        [
                            8279477500,
                            1724.7691440582275
                        ],
                        [
                            8298240375,
                            1734.8634052276611
                        ],
                        [
                            8323519625,
                            1748.6270084381104
                        ],
                        [
                            8340720916,
                            1758.7212772369385
                        ],
                        [
                            8359765208,
                            1775.598466873169
                        ],
                        [
                            8378557041,
                            1785.6927280426025
                        ],
                        [
                            8410939666,
                            1795.7869815826416
                        ],
                        [
                            8410943916,
                            1805.8432970046997
                        ],
                        [
                            8425360916,
                            1816.0318012237549
                        ],
                        [
                            8445906583,
                            1826.1260623931885
                        ],
                        [
                            8466644250,
                            1840.0535678863525
                        ]
                    ],
                    "n_avg_mb": 913.2734355926514,
                    "n_copy_mb_s": 1.584105463657453,
                    "n_core_utilization": 0.1407127589025659,
                    "n_cpu_percent_c": 33.2777427310471,
                    "n_cpu_percent_python": 5.987291172048388,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 913.2734355926514,
                    "n_malloc_mb": 913.2734355926514,
                    "n_mallocs": 1,
                    "n_peak_mb": 913.2734355926514,
                    "n_python_fraction": 0.8307421274471228,
                    "n_sys_percent": 4.263136848666266,
                    "n_usage_fraction": 0.4885235557314146
                },
                {
                    "line": "create_objects",
                    "lineno": 18,
                    "memory_samples": [
                        [
                            261610125,
                            20.217551231384277
                        ],
                        [
                            301142000,
                            30.311850547790527
                        ],
                        [
                            416539583,
                            50.50047206878662
                        ],
                        [
                            428785375,
                            60.59474849700928
                        ],
                        [
                            499454541,
                            70.68900203704834
                        ],
                        [
                            580060083,
                            80.78332424163818
                        ],
                        [
                            589268833,
                            90.87766170501709
                        ],
                        [
                            696517291,
                            111.06622982025146
                        ],
                        [
                            704891708,
                            121.16049861907959
                        ],
                        [
                            834404083,
                            141.3490972518921
                        ],
                        [
                            1009012416,
                            182.0473051071167
                        ],
                        [
                            1034015791,
                            212.33019638061523
                        ],
                        [
                            1218842625,
                            222.4245262145996
                        ],
                        [
                            1227537375,
                            232.51880264282227
                        ],
                        [
                            1236054708,
                            242.61307907104492
                        ],
                        [
                            1253000916,
                            262.8016777038574
                        ],
                        [
                            1479074666,
                            272.89602279663086
                        ],
                        [
                            1489525958,
                            282.99035263061523
                        ],
                        [
                            1502034500,
                            303.17888259887695
                        ],
                        [
                            3264248000,
                            639.9635620117188
                        ],
                        [
                            3614743333,
                            680.3407135009766
                        ],
                        [
                            3623388458,
                            690.4349670410156
                        ],
                        [
                            3632221958,
                            700.5293045043945
                        ],
                        [
                            3640760250,
                            710.6235809326172
                        ],
                        [
                            3647985000,
                            720.7179260253906
                        ],
                        [
                            3664640916,
                            740.9064712524414
                        ],
                        [
                            4055986708,
                            761.095085144043
                        ],
                        [
                            4064967041,
                            771.1894149780273
                        ],
                        [
                            4073457291,
                            781.2836675643921
                        ],
                        [
                            4081337875,
                            791.3779439926147
                        ],
                        [
                            4090467666,
                            801.4722204208374
                        ],
                        [
                            4097969208,
                            811.5665044784546
                        ],
                        [
                            4106332291,
                            821.6607809066772
                        ],
                        [
                            4116619250,
                            832.3625020980835
                        ],
                        [
                            4593388500,
                            862.6453399658203
                        ],
                        [
                            4617385916,
                            882.8339385986328
                        ],
                        [
                            4635792291,
                            903.0225219726562
                        ],
                        [
                            4643429250,
                            913.1167984008789
                        ],
                        [
                            4647218916,
                            923.2110748291016
                        ],
                        [
                            6363461625,
                            1250.7814483642578
                        ],
                        [
                            6371550250,
                            1260.8757247924805
                        ],
                        [
                            6380189750,
                            1270.9700622558594
                        ],
                        [
                            6388239791,
                            1281.064338684082
                        ],
                        [
                            6396353208,
                            1291.1586151123047
                        ],
                        [
                            6404479875,
                            1301.2528762817383
                        ],
                        [
                            6412694333,
                            1311.347152709961
                        ],
                        [
                            7020467041,
                            1331.5357666015625
                        ],
                        [
                            7028826708,
                            1341.6300430297852
                        ],
                        [
                            7038001916,
                            1351.7243127822876
                        ],
                        [
                            7054955500,
                            1371.9128580093384
                        ],
                        [
                            7080794958,
                            1402.1956949234009
                        ],
                        [
                            7089066625,
                            1412.2899713516235
                        ],
                        [
                            7097369833,
                            1422.3842630386353
                        ],
                        [
                            7105619625,
                            1432.478539466858
                        ],
                        [
                            7113786250,
                            1442.5728158950806
                        ],
                        [
                            7131353291,
                            1462.7613763809204
                        ],
                        [
                            7139757875,
                            1472.855652809143
                        ],
                        [
                            7871402916,
                            1493.0442743301392
                        ],
                        [
                            7885541458,
                            1503.13858127594
                        ],
                        [
                            7894426000,
                            1513.2328577041626
                        ],
                        [
                            7902203666,
                            1523.3271951675415
                        ]
                    ],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 16.500674606180905,
                    "n_core_utilization": 0.10369815749347289,
                    "n_cpu_percent_c": 24.557957425415545,
                    "n_cpu_percent_python": 3.4314435014157185,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 610.9608573913574,
                    "n_malloc_mb": 610.9608573913574,
                    "n_mallocs": 0,
                    "n_peak_mb": 610.9608573913574,
                    "n_python_fraction": 0.9999924982518451,
                    "n_sys_percent": 3.6278726052745682,
                    "n_usage_fraction": 0.32681205741175867
                },
                {
                    "line": "main",
                    "lineno": 26,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0024623786225143854,
                    "n_cpu_percent_c": 0.020216730627039683,
                    "n_cpu_percent_python": 0.31902848708448667,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 13.437889403653735,
                    "n_usage_fraction": 0.0
                }
            ],
            "imports": [
                "import numpy as np",
                "import time"
            ],
            "leaks": {
                "15": {
                    "likelihood": 0.9848484848484849,
                    "velocity_mb_s": 88.96306998555474
                },
                "21": {
                    "likelihood": 0.9821428571428571,
                    "velocity_mb_s": 0.0
                }
            },
            "lines": [
                {
                    "end_outermost_loop": 1,
                    "end_region_line": 1,
                    "line": "import numpy as np\n",
                    "lineno": 1,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.16171629192290818,
                    "n_cpu_percent_c": 6.897795884236699,
                    "n_cpu_percent_python": 0.15929643649092604,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 1,
                    "start_region_line": 1
                },
                {
                    "end_outermost_loop": 2,
                    "end_region_line": 2,
                    "line": "import time\n",
                    "lineno": 2,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 2,
                    "start_region_line": 2
                },
                {
                    "end_outermost_loop": 3,
                    "end_region_line": 3,
                    "line": "\n",
                    "lineno": 3,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 3,
                    "start_region_line": 3
                },
                {
                    "end_outermost_loop": 9,
                    "end_region_line": 9,
                    "line": "def cpu_intensive_task():\n",
                    "lineno": 4,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 4,
                    "start_region_line": 4
                },
                {
                    "end_outermost_loop": 9,
                    "end_region_line": 9,
                    "line": "    # \u8fdb\u884c\u4e00\u4e9b CPU \u5bc6\u96c6\u578b\u7684\u8ba1\u7b97\u64cd\u4f5c\n",
                    "lineno": 5,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 4,
                    "start_region_line": 4
                },
                {
                    "end_outermost_loop": 6,
                    "end_region_line": 9,
                    "line": "    matrix_a = np.random.rand(1000, 1000)\n",
                    "lineno": 6,
                    "memory_samples": [
                        [
                            7904658833,
                            1540.6874551773071
                        ]
                    ],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 5.702653698707739,
                    "n_core_utilization": 0.08640051031057075,
                    "n_cpu_percent_c": 0.0416981912480421,
                    "n_cpu_percent_python": 0.09175528935647621,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 17.266016960144043,
                    "n_malloc_mb": 17.266016960144043,
                    "n_mallocs": 0,
                    "n_peak_mb": 17.266016960144043,
                    "n_python_fraction": 0.583553,
                    "n_sys_percent": 0.021005654098290073,
                    "n_usage_fraction": 0.009235849494751635,
                    "start_outermost_loop": 6,
                    "start_region_line": 4
                },
                {
                    "end_outermost_loop": 7,
                    "end_region_line": 9,
                    "line": "    matrix_b = np.random.rand(1000, 1000)\n",
                    "lineno": 7,
                    "memory_samples": [
                        [
                            1514325250,
                            320.4333305358887
                        ],
                        [
                            4651195375,
                            938.8812103271484
                        ]
                    ],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.08607619490447269,
                    "n_cpu_percent_c": 0.025092284940414055,
                    "n_cpu_percent_python": 0.04570543704993635,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 32.73609733581543,
                    "n_malloc_mb": 32.73609733581543,
                    "n_mallocs": 0,
                    "n_peak_mb": 32.73609733581543,
                    "n_python_fraction": 0.2971829049861671,
                    "n_sys_percent": 0.011452338051129916,
                    "n_usage_fraction": 0.017511025776069254,
                    "start_outermost_loop": 7,
                    "start_region_line": 4
                },
                {
                    "end_outermost_loop": 8,
                    "end_region_line": 9,
                    "line": "    result = np.dot(matrix_a, matrix_b)\n",
                    "lineno": 8,
                    "memory_samples": [
                        [
                            7938303875,
                            1556.0007486343384
                        ]
                    ],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.674798515756818,
                    "n_cpu_percent_c": 3.082354186812126,
                    "n_cpu_percent_python": 0.15929643649092604,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 15.219050407409668,
                    "n_malloc_mb": 15.219050407409668,
                    "n_mallocs": 0,
                    "n_peak_mb": 15.219050407409668,
                    "n_python_fraction": 0.00043,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.008140896614450076,
                    "start_outermost_loop": 8,
                    "start_region_line": 4
                },
                {
                    "end_outermost_loop": 9,
                    "end_region_line": 9,
                    "line": "    return result\n",
                    "lineno": 9,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 9,
                    "start_region_line": 4
                },
                {
                    "end_outermost_loop": 10,
                    "end_region_line": 10,
                    "line": "\n",
                    "lineno": 10,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 10,
                    "start_region_line": 10
                },
                {
                    "end_outermost_loop": 16,
                    "end_region_line": 16,
                    "line": "def memory_intensive_task():\n",
                    "lineno": 11,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 11,
                    "start_region_line": 11
                },
                {
                    "end_outermost_loop": 16,
                    "end_region_line": 16,
                    "line": "    # \u8fdb\u884c\u4e00\u4e9b\u5185\u5b58\u5bc6\u96c6\u578b\u7684\u64cd\u4f5c\n",
                    "lineno": 12,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 11,
                    "start_region_line": 11
                },
                {
                    "end_outermost_loop": 13,
                    "end_region_line": 16,
                    "line": "    big_list = []\n",
                    "lineno": 13,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 13,
                    "start_region_line": 11
                },
                {
                    "end_outermost_loop": 15,
                    "end_region_line": 15,
                    "line": "    for _ in range(10000):\n",
                    "lineno": 14,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 14,
                    "start_region_line": 14
                },
                {
                    "end_outermost_loop": 15,
                    "end_region_line": 15,
                    "line": "        big_list.extend(list(np.random.rand(1000)))\n",
                    "lineno": 15,
                    "memory_samples": [
                        [
                            1586911500,
                            330.52758407592773
                        ],
                        [
                            1586926083,
                            340.68763256073
                        ],
                        [
                            1628119958,
                            351.0104064941406
                        ],
                        [
                            1628134583,
                            361.01042461395264
                        ],
                        [
                            1699588583,
                            355.8333511352539
                        ],
                        [
                            1699601458,
                            365.83337688446045
                        ],
                        [
                            1699608666,
                            375.833402633667
                        ],
                        [
                            1699616000,
                            387.03852939605713
                        ],
                        [
                            1723735291,
                            397.41551971435547
                        ],
                        [
                            1739026000,
                            407.50978088378906
                        ],
                        [
                            1767452708,
                            419.01417541503906
                        ],
                        [
                            1797145125,
                            432.32678985595703
                        ],
                        [
                            1822594791,
                            442.4210433959961
                        ],
                        [
                            1834565541,
                            452.5153121948242
                        ],
                        [
                            1850294125,
                            464.1138000488281
                        ],
                        [
                            1869758250,
                            474.2080535888672
                        ],
                        [
                            1883884333,
                            484.3023147583008
                        ],
                        [
                            1903065791,
                            494.3965759277344
                        ],
                        [
                            1916763375,
                            504.49083709716797
                        ],
                        [
                            1936522083,
                            514.5851058959961
                        ],
                        [
                            1956721000,
                            528.3486099243164
                        ],
                        [
                            1975292166,
                            538.44287109375
                        ],
                        [
                            2001179708,
                            555.3200836181641
                        ],
                        [
                            2020334375,
                            565.4143447875977
                        ],
                        [
                            2039004750,
                            575.5086135864258
                        ],
                        [
                            2053672583,
                            585.6590805053711
                        ],
                        [
                            2070966625,
                            595.7533493041992
                        ],
                        [
                            2092377500,
                            605.8476104736328
                        ],
                        [
                            2108046083,
                            619.7749938964844
                        ],
                        [
                            4710785583,
                            933.5699081420898
                        ],
                        [
                            4720401708,
                            943.9127807617188
                        ],
                        [
                            4740086708,
                            954.0070343017578
                        ],
                        [
                            4764107375,
                            964.9048156738281
                        ],
                        [
                            4789696916,
                            975.920166015625
                        ],
                        [
                            4802466750,
                            986.0144195556641
                        ],
                        [
                            4842719375,
                            998.139533996582
                        ],
                        [
                            4842724416,
                            1008.1395444869995
                        ],
                        [
                            4860954000,
                            1018.3280487060547
                        ],
                        [
                            4947300750,
                            1029.8319778442383
                        ],
                        [
                            4947305000,
                            1043.0501890182495
                        ],
                        [
                            4947307208,
                            1053.050199508667
                        ],
                        [
                            4947309791,
                            1063.0502099990845
                        ],
                        [
                            4960439375,
                            1074.9309539794922
                        ],
                        [
                            4983162375,
                            1085.0252151489258
                        ],
                        [
                            4994524916,
                            1095.1194763183594
                        ],
                        [
                            5012238333,
                            1105.2137298583984
                        ],
                        [
                            5025768458,
                            1115.307991027832
                        ],
                        [
                            5042824291,
                            1125.4022521972656
                        ],
                        [
                            5064472000,
                            1139.1659317016602
                        ],
                        [
                            5084109083,
                            1149.2601928710938
                        ],
                        [
                            5104852875,
                            1166.1375198364258
                        ],
                        [
                            5123068916,
                            1176.2317810058594
                        ],
                        [
                            5142381125,
                            1186.3260345458984
                        ],
                        [
                            5152115333,
                            1196.4767532348633
                        ],
                        [
                            5171178041,
                            1206.5710144042969
                        ],
                        [
                            5191111333,
                            1216.665283203125
                        ],
                        [
                            5208898958,
                            1230.5928344726562
                        ],
                        [
                            7974245750,
                            1551.1085367202759
                        ],
                        [
                            8078905291,
                            1562.0294351577759
                        ],
                        [
                            8078910166,
                            1572.0294609069824
                        ],
                        [
                            8078912625,
                            1582.029486656189
                        ],
                        [
                            8078915000,
                            1592.0295133590698
                        ],
                        [
                            8078917166,
                            1602.0295238494873
                        ],
                        [
                            8185784375,
                            1612.5007495880127
                        ],
                        [
                            8185799083,
                            1622.5007753372192
                        ],
                        [
                            8185810708,
                            1632.5007934570312
                        ],
                        [
                            8185817208,
                            1642.5008192062378
                        ],
                        [
                            8185823583,
                            1652.5008449554443
                        ],
                        [
                            8185829875,
                            1662.5008554458618
                        ],
                        [
                            8204504416,
                            1673.0663242340088
                        ],
                        [
                            8215791208,
                            1684.3921070098877
                        ],
                        [
                            8234073750,
                            1694.4863681793213
                        ],
                        [
                            8249107583,
                            1704.5806293487549
                        ],
                        [
                            8267385958,
                            1714.674882888794
                        ],
                        [
                            8279477500,
                            1724.7691440582275
                        ],
                        [
                            8298240375,
                            1734.8634052276611
                        ],
                        [
                            8323519625,
                            1748.6270084381104
                        ],
                        [
                            8340720916,
                            1758.7212772369385
                        ],
                        [
                            8359765208,
                            1775.598466873169
                        ],
                        [
                            8378557041,
                            1785.6927280426025
                        ],
                        [
                            8410939666,
                            1795.7869815826416
                        ],
                        [
                            8410943916,
                            1805.8432970046997
                        ],
                        [
                            8425360916,
                            1816.0318012237549
                        ],
                        [
                            8445906583,
                            1826.1260623931885
                        ],
                        [
                            8466644250,
                            1840.0535678863525
                        ]
                    ],
                    "n_avg_mb": 913.2734355926514,
                    "n_copy_mb_s": 1.584105463657453,
                    "n_core_utilization": 0.1407127589025659,
                    "n_cpu_percent_c": 33.2777427310471,
                    "n_cpu_percent_python": 5.987291172048388,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 913.2734355926514,
                    "n_malloc_mb": 913.2734355926514,
                    "n_mallocs": 1,
                    "n_peak_mb": 913.2734355926514,
                    "n_python_fraction": 0.8307421274471228,
                    "n_sys_percent": 4.263136848666266,
                    "n_usage_fraction": 0.4885235557314146,
                    "start_outermost_loop": 14,
                    "start_region_line": 14
                },
                {
                    "end_outermost_loop": 16,
                    "end_region_line": 16,
                    "line": "    return big_list\n",
                    "lineno": 16,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 16,
                    "start_region_line": 11
                },
                {
                    "end_outermost_loop": 17,
                    "end_region_line": 17,
                    "line": "\n",
                    "lineno": 17,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 17,
                    "start_region_line": 17
                },
                {
                    "end_outermost_loop": 24,
                    "end_region_line": 24,
                    "line": "def create_objects(objs): \n",
                    "lineno": 18,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 18,
                    "start_region_line": 18
                },
                {
                    "end_outermost_loop": 24,
                    "end_region_line": 24,
                    "line": "    # \u4ea7\u751f\u5927\u91cf\u7684\u5bf9\u8c61\uff0c\u5bfc\u81f4\u5185\u5b58\u5360\u7528\u589e\u52a0\n",
                    "lineno": 19,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 18,
                    "start_region_line": 18
                },
                {
                    "end_outermost_loop": 24,
                    "end_region_line": 24,
                    "line": "    for _ in range(1000000):\n",
                    "lineno": 20,
                    "memory_samples": [
                        [
                            1244404625,
                            252.70733261108398
                        ],
                        [
                            3272608750,
                            650.0578384399414
                        ],
                        [
                            3280982916,
                            660.1521148681641
                        ],
                        [
                            4125054791,
                            842.4567632675171
                        ],
                        [
                            7011032708,
                            1321.44140625
                        ],
                        [
                            7148026458,
                            1482.9499139785767
                        ]
                    ],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 60.00012397766113,
                    "n_malloc_mb": 60.00012397766113,
                    "n_mallocs": 0,
                    "n_peak_mb": 60.00012397766113,
                    "n_python_fraction": 1.0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.03209495948042286,
                    "start_outermost_loop": 20,
                    "start_region_line": 20
                },
                {
                    "end_outermost_loop": 24,
                    "end_region_line": 24,
                    "line": "        objs.append({\n",
                    "lineno": 21,
                    "memory_samples": [
                        [
                            261610125,
                            20.217551231384277
                        ],
                        [
                            301142000,
                            30.311850547790527
                        ],
                        [
                            416539583,
                            50.50047206878662
                        ],
                        [
                            428785375,
                            60.59474849700928
                        ],
                        [
                            499454541,
                            70.68900203704834
                        ],
                        [
                            580060083,
                            80.78332424163818
                        ],
                        [
                            589268833,
                            90.87766170501709
                        ],
                        [
                            696517291,
                            111.06622982025146
                        ],
                        [
                            704891708,
                            121.16049861907959
                        ],
                        [
                            834404083,
                            141.3490972518921
                        ],
                        [
                            1009012416,
                            182.0473051071167
                        ],
                        [
                            1034015791,
                            212.33019638061523
                        ],
                        [
                            1218842625,
                            222.4245262145996
                        ],
                        [
                            1227537375,
                            232.51880264282227
                        ],
                        [
                            1236054708,
                            242.61307907104492
                        ],
                        [
                            1253000916,
                            262.8016777038574
                        ],
                        [
                            1479074666,
                            272.89602279663086
                        ],
                        [
                            1489525958,
                            282.99035263061523
                        ],
                        [
                            1502034500,
                            303.17888259887695
                        ],
                        [
                            3264248000,
                            639.9635620117188
                        ],
                        [
                            3614743333,
                            680.3407135009766
                        ],
                        [
                            3623388458,
                            690.4349670410156
                        ],
                        [
                            3632221958,
                            700.5293045043945
                        ],
                        [
                            3640760250,
                            710.6235809326172
                        ],
                        [
                            3647985000,
                            720.7179260253906
                        ],
                        [
                            3664640916,
                            740.9064712524414
                        ],
                        [
                            4055986708,
                            761.095085144043
                        ],
                        [
                            4064967041,
                            771.1894149780273
                        ],
                        [
                            4073457291,
                            781.2836675643921
                        ],
                        [
                            4081337875,
                            791.3779439926147
                        ],
                        [
                            4090467666,
                            801.4722204208374
                        ],
                        [
                            4097969208,
                            811.5665044784546
                        ],
                        [
                            4106332291,
                            821.6607809066772
                        ],
                        [
                            4116619250,
                            832.3625020980835
                        ],
                        [
                            4593388500,
                            862.6453399658203
                        ],
                        [
                            4617385916,
                            882.8339385986328
                        ],
                        [
                            4635792291,
                            903.0225219726562
                        ],
                        [
                            4643429250,
                            913.1167984008789
                        ],
                        [
                            4647218916,
                            923.2110748291016
                        ],
                        [
                            6363461625,
                            1250.7814483642578
                        ],
                        [
                            6371550250,
                            1260.8757247924805
                        ],
                        [
                            6380189750,
                            1270.9700622558594
                        ],
                        [
                            6388239791,
                            1281.064338684082
                        ],
                        [
                            6396353208,
                            1291.1586151123047
                        ],
                        [
                            6404479875,
                            1301.2528762817383
                        ],
                        [
                            6412694333,
                            1311.347152709961
                        ],
                        [
                            7020467041,
                            1331.5357666015625
                        ],
                        [
                            7028826708,
                            1341.6300430297852
                        ],
                        [
                            7038001916,
                            1351.7243127822876
                        ],
                        [
                            7054955500,
                            1371.9128580093384
                        ],
                        [
                            7080794958,
                            1402.1956949234009
                        ],
                        [
                            7089066625,
                            1412.2899713516235
                        ],
                        [
                            7097369833,
                            1422.3842630386353
                        ],
                        [
                            7105619625,
                            1432.478539466858
                        ],
                        [
                            7113786250,
                            1442.5728158950806
                        ],
                        [
                            7131353291,
                            1462.7613763809204
                        ],
                        [
                            7139757875,
                            1472.855652809143
                        ],
                        [
                            7871402916,
                            1493.0442743301392
                        ],
                        [
                            7885541458,
                            1503.13858127594
                        ],
                        [
                            7894426000,
                            1513.2328577041626
                        ],
                        [
                            7902203666,
                            1523.3271951675415
                        ]
                    ],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 16.500674606180905,
                    "n_core_utilization": 0.10369815749347289,
                    "n_cpu_percent_c": 24.557957425415545,
                    "n_cpu_percent_python": 3.431443501415719,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 610.9608573913574,
                    "n_malloc_mb": 610.9608573913574,
                    "n_mallocs": 0,
                    "n_peak_mb": 610.9608573913574,
                    "n_python_fraction": 0.9999924982518451,
                    "n_sys_percent": 3.6278726052745647,
                    "n_usage_fraction": 0.32681205741175867,
                    "start_outermost_loop": 20,
                    "start_region_line": 20
                },
                {
                    "end_outermost_loop": 24,
                    "end_region_line": 24,
                    "line": "            \"a\" : {},\n",
                    "lineno": 22,
                    "memory_samples": [
                        [
                            351806541,
                            40.40611934661865
                        ],
                        [
                            997736708,
                            171.63191890716553
                        ],
                        [
                            1025712333,
                            202.23586559295654
                        ],
                        [
                            1498082250,
                            293.0846061706543
                        ],
                        [
                            3606348333,
                            670.2463836669922
                        ]
                    ],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 50.00010585784912,
                    "n_malloc_mb": 50.00010585784912,
                    "n_mallocs": 0,
                    "n_peak_mb": 50.00010585784912,
                    "n_python_fraction": 1.0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.026745800927377952,
                    "start_outermost_loop": 20,
                    "start_region_line": 20
                },
                {
                    "end_outermost_loop": 24,
                    "end_region_line": 24,
                    "line": "            \"b\" : []\n",
                    "lineno": 23,
                    "memory_samples": [
                        [
                            210399375,
                            10.000018119812012
                        ],
                        [
                            597671458,
                            100.97196102142334
                        ],
                        [
                            713055750,
                            131.25475978851318
                        ],
                        [
                            842850541,
                            151.4433889389038
                        ],
                        [
                            851186666,
                            161.53766536712646
                        ],
                        [
                            1017241250,
                            192.1415891647339
                        ],
                        [
                            3255989916,
                            629.8692779541016
                        ],
                        [
                            3656659125,
                            730.8121948242188
                        ],
                        [
                            3673033958,
                            751.0007476806641
                        ],
                        [
                            4133514583,
                            852.5510625839233
                        ],
                        [
                            4607734916,
                            872.7396087646484
                        ],
                        [
                            4626339333,
                            892.92822265625
                        ],
                        [
                            6355074250,
                            1240.6871032714844
                        ],
                        [
                            7046763541,
                            1361.8185815811157
                        ],
                        [
                            7063489708,
                            1382.0071268081665
                        ],
                        [
                            7071901333,
                            1392.1014184951782
                        ],
                        [
                            7123047083,
                            1452.6670999526978
                        ]
                    ],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 170.00060558319092,
                    "n_malloc_mb": 170.00060558319092,
                    "n_mallocs": 0,
                    "n_peak_mb": 170.00060558319092,
                    "n_python_fraction": 0.9886515939481221,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.09093585456375498,
                    "start_outermost_loop": 20,
                    "start_region_line": 20
                },
                {
                    "end_outermost_loop": 24,
                    "end_region_line": 24,
                    "line": "        })\n",
                    "lineno": 24,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 20,
                    "start_region_line": 20
                },
                {
                    "end_outermost_loop": 25,
                    "end_region_line": 25,
                    "line": "\n",
                    "lineno": 25,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 25,
                    "start_region_line": 25
                },
                {
                    "end_outermost_loop": 46,
                    "end_region_line": 46,
                    "line": "def main():\n",
                    "lineno": 26,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 26,
                    "start_region_line": 26
                },
                {
                    "end_outermost_loop": 27,
                    "end_region_line": 46,
                    "line": "    objs = []\n",
                    "lineno": 27,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 27,
                    "start_region_line": 26
                },
                {
                    "end_outermost_loop": 46,
                    "end_region_line": 46,
                    "line": "    for _ in range(3):  # \u6267\u884c3\u6b21\n",
                    "lineno": 28,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 28,
                    "start_region_line": 28
                },
                {
                    "end_outermost_loop": 46,
                    "end_region_line": 46,
                    "line": "        create_objects(objs)  # \u4ea7\u751f\u5927\u91cf\u7684\u5bf9\u8c61\uff0c\u5bfc\u81f4\u5185\u5b58\u5360\u7528\u589e\u52a0\n",
                    "lineno": 29,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 28,
                    "start_region_line": 28
                },
                {
                    "end_outermost_loop": 46,
                    "end_region_line": 46,
                    "line": "        print(f\"=== Iteration {_ + 1} ===\")\n",
                    "lineno": 30,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 28,
                    "start_region_line": 28
                },
                {
                    "end_outermost_loop": 46,
                    "end_region_line": 46,
                    "line": "        # \u6267\u884c CPU \u5bc6\u96c6\u578b\u4efb\u52a1\n",
                    "lineno": 31,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 28,
                    "start_region_line": 28
                },
                {
                    "end_outermost_loop": 46,
                    "end_region_line": 46,
                    "line": "        print(\"Starting CPU intensive task...\")\n",
                    "lineno": 32,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 28,
                    "start_region_line": 28
                },
                {
                    "end_outermost_loop": 46,
                    "end_region_line": 46,
                    "line": "        start_time_cpu = time.time()\n",
                    "lineno": 33,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 28,
                    "start_region_line": 28
                },
                {
                    "end_outermost_loop": 46,
                    "end_region_line": 46,
                    "line": "        result_cpu = cpu_intensive_task()\n",
                    "lineno": 34,
                    "memory_samples": [
                        [
                            4694414500,
                            923.5698928833008
                        ],
                        [
                            7938319000,
                            1540.5938987731934
                        ]
                    ],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 28,
                    "start_region_line": 28
                },
                {
                    "end_outermost_loop": 46,
                    "end_region_line": 46,
                    "line": "        end_time_cpu = time.time()\n",
                    "lineno": 35,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 28,
                    "start_region_line": 28
                },
                {
                    "end_outermost_loop": 46,
                    "end_region_line": 46,
                    "line": "        print(\"CPU intensive task completed in\", end_time_cpu - start_time_cpu, \"seconds\")\n",
                    "lineno": 36,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 28,
                    "start_region_line": 28
                },
                {
                    "end_outermost_loop": 46,
                    "end_region_line": 46,
                    "line": "\n",
                    "lineno": 37,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 28,
                    "start_region_line": 28
                },
                {
                    "end_outermost_loop": 46,
                    "end_region_line": 46,
                    "line": "        # \u6267\u884c\u5185\u5b58\u5bc6\u96c6\u578b\u4efb\u52a1\n",
                    "lineno": 38,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 28,
                    "start_region_line": 28
                },
                {
                    "end_outermost_loop": 46,
                    "end_region_line": 46,
                    "line": "        print(\"Starting memory intensive task...\")\n",
                    "lineno": 39,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 28,
                    "start_region_line": 28
                },
                {
                    "end_outermost_loop": 46,
                    "end_region_line": 46,
                    "line": "        start_time_mem = time.time()\n",
                    "lineno": 40,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 28,
                    "start_region_line": 28
                },
                {
                    "end_outermost_loop": 46,
                    "end_region_line": 46,
                    "line": "        result_mem = memory_intensive_task()\n",
                    "lineno": 41,
                    "memory_samples": [
                        [
                            8629700083,
                            1830.1477909088135
                        ],
                        [
                            8629702083,
                            1820.147783279419
                        ],
                        [
                            8629703333,
                            1810.1477756500244
                        ],
                        [
                            8629704416,
                            1800.1477680206299
                        ],
                        [
                            8629705416,
                            1790.1477603912354
                        ],
                        [
                            8629706375,
                            1780.1477527618408
                        ],
                        [
                            8629707250,
                            1770.1477451324463
                        ],
                        [
                            8629708125,
                            1760.1477375030518
                        ],
                        [
                            8629709125,
                            1750.1477298736572
                        ],
                        [
                            8629710083,
                            1740.1477222442627
                        ],
                        [
                            8629710916,
                            1730.1477146148682
                        ],
                        [
                            8629711750,
                            1720.1477069854736
                        ],
                        [
                            8629712625,
                            1710.147699356079
                        ],
                        [
                            8629713458,
                            1700.1476917266846
                        ],
                        [
                            8629714333,
                            1690.14768409729
                        ],
                        [
                            8629715208,
                            1680.1476764678955
                        ],
                        [
                            8629716166,
                            1670.147668838501
                        ],
                        [
                            8629717125,
                            1660.1476612091064
                        ],
                        [
                            8629718000,
                            1650.147653579712
                        ],
                        [
                            8629718833,
                            1640.1476459503174
                        ],
                        [
                            8629719708,
                            1630.1476383209229
                        ],
                        [
                            8629720583,
                            1620.1476306915283
                        ],
                        [
                            8629721375,
                            1533.0437717437744
                        ]
                    ],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 28,
                    "start_region_line": 28
                },
                {
                    "end_outermost_loop": 46,
                    "end_region_line": 46,
                    "line": "        end_time_mem = time.time()\n",
                    "lineno": 42,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.08907539801530559,
                    "n_cpu_percent_c": 0.7233185221817022,
                    "n_cpu_percent_python": 0.047297978276163624,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.09451182636190632,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 28,
                    "start_region_line": 28
                },
                {
                    "end_outermost_loop": 46,
                    "end_region_line": 46,
                    "line": "        print(\"Memory intensive task completed in\", end_time_mem - start_time_mem, \"seconds\")\n",
                    "lineno": 43,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 28,
                    "start_region_line": 28
                },
                {
                    "end_outermost_loop": 46,
                    "end_region_line": 46,
                    "line": "\n",
                    "lineno": 44,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 28,
                    "start_region_line": 28
                },
                {
                    "end_outermost_loop": 46,
                    "end_region_line": 46,
                    "line": "        # \u4f11\u7720\u4e00\u6bb5\u65f6\u95f4\u540e\u518d\u6b21\u6267\u884c\n",
                    "lineno": 45,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 28,
                    "start_region_line": 28
                },
                {
                    "end_outermost_loop": 46,
                    "end_region_line": 46,
                    "line": "        time.sleep(1)\n",
                    "lineno": 46,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0021059464439432277,
                    "n_cpu_percent_c": 0.0001894285933832628,
                    "n_cpu_percent_python": 0.2717305088083232,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 12.640086357143781,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 28,
                    "start_region_line": 28
                },
                {
                    "end_outermost_loop": 47,
                    "end_region_line": 47,
                    "line": "\n",
                    "lineno": 47,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 47,
                    "start_region_line": 47
                },
                {
                    "end_outermost_loop": 48,
                    "end_region_line": 48,
                    "line": "\n",
                    "lineno": 48,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 48,
                    "start_region_line": 48
                },
                {
                    "end_outermost_loop": 50,
                    "end_region_line": 49,
                    "line": "if __name__ == \"__main__\":\n",
                    "lineno": 49,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 49,
                    "start_region_line": 49
                },
                {
                    "end_outermost_loop": 50,
                    "end_region_line": 50,
                    "line": "    main()\n",
                    "lineno": 50,
                    "memory_samples": [],
                    "n_avg_mb": 0.0,
                    "n_copy_mb_s": 0.0,
                    "n_core_utilization": 0.0,
                    "n_cpu_percent_c": 0.0,
                    "n_cpu_percent_python": 0.0,
                    "n_gpu_avg_memory_mb": 0.0,
                    "n_gpu_peak_memory_mb": 0.0,
                    "n_gpu_percent": 0,
                    "n_growth_mb": 0.0,
                    "n_malloc_mb": 0.0,
                    "n_mallocs": 0,
                    "n_peak_mb": 0.0,
                    "n_python_fraction": 0,
                    "n_sys_percent": 0.0,
                    "n_usage_fraction": 0.0,
                    "start_outermost_loop": 50,
                    "start_region_line": 50
                }
            ],
            "percent_cpu_time": 99.45803104400815
        }
    },
    "gpu": false,
    "growth_rate": 82.00479344701023,
    "max_footprint_fname": "/Users/xclin/python_thread/test_new.py",
    "max_footprint_lineno": 15,
    "max_footprint_mb": 1840.1478109359741,
    "memory": true,
    "program": "/Users/xclin/python_thread/test_new.py",
    "samples": [
        [
            210362125,
            10.000018119812012
        ],
        [
            351797791,
            40.500362396240234
        ],
        [
            416531708,
            50.50047206878662
        ],
        [
            428780000,
            60.68899154663086
        ],
        [
            580052416,
            80.78332424163818
        ],
        [
            597667583,
            101.06620407104492
        ],
        [
            713051625,
            131.34900283813477
        ],
        [
            834398000,
            141.3490972518921
        ],
        [
            851183166,
            161.63190841674805
        ],
        [
            997730916,
            171.63191890716553
        ],
        [
            1034012416,
            212.42443943023682
        ],
        [
            1252995708,
            262.895920753479
        ],
        [
            1479066833,
            272.89602279663086
        ],
        [
            1498077958,
            293.0846061706543
        ],
        [
            1502031083,
            303.27312564849854
        ],
        [
            1514319708,
            320.52757358551025
        ],
        [
            1586859875,
            330.52758407592773
        ],
        [
            1586873958,
            340.87611865997314
        ],
        [
            1628100541,
            351.1046495437622
        ],
        [
            1628102833,
            361.1989107131958
        ],
        [
            1699529541,
            345.8333330154419
        ],
        [
            1699534083,
            355.9275941848755
        ],
        [
            1699535625,
            365.92761993408203
        ],
        [
            1699536958,
            366.0218629837036
        ],
        [
            1699538125,
            376.02188873291016
        ],
        [
            1699543500,
            376.11613178253174
        ],
        [
            1699545375,
            387.41550159454346
        ],
        [
            2001175583,
            555.4143266677856
        ],
        [
            2108039583,
            619.869236946106
        ],
        [
            3255982708,
            629.8692779541016
        ],
        [
            3280979375,
            660.2463579177856
        ],
        [
            3606340333,
            670.2463836669922
        ],
        [
            3673028375,
            751.0949907302856
        ],
        [
            4055977083,
            761.095085144043
        ],
        [
            4133511041,
            852.6453056335449
        ],
        [
            4593379208,
            862.6453399658203
        ],
        [
            4635787291,
            903.0225219726562
        ],
        [
            4643421708,
            913.1167984008789
        ],
        [
            4651190000,
            938.97545337677
        ],
        [
            4694381958,
            923.5698928833008
        ],
        [
            4710764083,
            933.5699081420898
        ],
        [
            4789690041,
            975.920166015625
        ],
        [
            4802462375,
            986.1086626052856
        ],
        [
            4842711291,
            998.2337770462036
        ],
        [
            4842711833,
            1008.2337875366211
        ],
        [
            4842712333,
            1008.3280305862427
        ],
        [
            4947291875,
            1029.8319778442383
        ],
        [
            4947293250,
            1043.144432067871
        ],
        [
            4947293625,
            1043.2386751174927
        ],
        [
            4947293916,
            1053.2386856079102
        ],
        [
            4947294250,
            1053.3329286575317
        ],
        [
            4947294666,
            1063.3329391479492
        ],
        [
            4947295083,
            1063.4271821975708
        ],
        [
            4983156916,
            1085.0252151489258
        ],
        [
            5025764958,
            1115.4022340774536
        ],
        [
            5084099833,
            1149.2601928710938
        ],
        [
            5104847875,
            1166.2317628860474
        ],
        [
            5142374583,
            1186.3260345458984
        ],
        [
            5152112041,
            1196.5709962844849
        ],
        [
            5191105916,
            1216.665283203125
        ],
        [
            6355067083,
            1240.6871032714844
        ],
        [
            6412690666,
            1311.4413957595825
        ],
        [
            7011025250,
            1321.44140625
        ],
        [
            7871396333,
            1493.0442743301392
        ],
        [
            7885536458,
            1503.13858127594
        ],
        [
            7904653541,
            1540.7816982269287
        ],
        [
            7938279666,
            1556.09499168396
        ],
        [
            7938283208,
            1540.688141822815
        ],
        [
            7974227791,
            1551.2027797698975
        ],
        [
            8078889916,
            1562.0294351577759
        ],
        [
            8078890916,
            1562.1236782073975
        ],
        [
            8078891333,
            1572.123703956604
        ],
        [
            8078896750,
            1572.2179470062256
        ],
        [
            8078897125,
            1582.2179727554321
        ],
        [
            8078897708,
            1592.3122425079346
        ],
        [
            8078898041,
            1592.4064855575562
        ],
        [
            8078898333,
            1602.4064960479736
        ],
        [
            8078898625,
            1602.5007390975952
        ],
        [
            8185756791,
            1612.5949926376343
        ],
        [
            8185757958,
            1622.5950183868408
        ],
        [
            8185758958,
            1622.6892614364624
        ],
        [
            8185760875,
            1632.783522605896
        ],
        [
            8185761833,
            1642.7835483551025
        ],
        [
            8185763000,
            1642.8777914047241
        ],
        [
            8185764125,
            1652.8778171539307
        ],
        [
            8185764958,
            1652.9720602035522
        ],
        [
            8185765958,
            1662.9720706939697
        ],
        [
            8185767000,
            1663.0663137435913
        ],
        [
            8279473833,
            1724.8633871078491
        ],
        [
            8340716791,
            1758.7212772369385
        ],
        [
            8359760291,
            1775.6927099227905
        ],
        [
            8378552750,
            1785.7869710922241
        ],
        [
            8410932416,
            1795.7869815826416
        ],
        [
            8410933208,
            1795.8812246322632
        ],
        [
            8410935250,
            1806.0317831039429
        ],
        [
            8466639791,
            1840.1478109359741
        ],
        [
            8629684291,
            1820.147783279419
        ],
        [
            8629688041,
            1750.1477298736572
        ],
        [
            8629693833,
            1620.1476306915283
        ],
        [
            8629694208,
            1533.0437717437744
        ]
    ],
    "stacks": []
}

    </script>
    <script src="https://cdn.jsdelivr.net/npm/vega@5"></script>
    <script src="https://cdn.jsdelivr.net/npm/vega-lite@5"></script>
    <script src="https://cdn.jsdelivr.net/npm/vega-embed@6"></script>
    <!--
	<script src="https://cdn.jsdelivr.net/npm/vega@5.21.0"></script>
	<script src="https://cdn.jsdelivr.net/npm/vega-lite@5.2.0"></script>
	<script src="https://cdn.jsdelivr.net/npm/vega-embed@6.20.0"></script>
	-->
  </head>
  <body>
    <a href="https://github.com/plasma-umass/scalene">
      <p class="text-center">
	<img src="https://github.com/plasma-umass/scalene/raw/master/scalene/scalene-gui/scalene-image.png" height="100">
      </p>
    </a>
    <p />
	<div class="d-flex justify-content-center">
	  <details id="ai-optimization-options">
	    <summary style="font-size:0.8rem; color: blue">AI optimization options</summary>
	  <!-- <label for='demoinput' style="padding: 5px 5px; border-radius: 5px; border: 1px ridge black; font-size: 0.8rem; height: auto;">demo</label>
	  <input style="height: 0; width: 0; opacity:0" type='button' id='demoinput' accept='.json' onclick="loadDemo();">
	  -->
        <label for="service-select" style="font-size: 0.8rem">AI service provider:</label>
        <select style="font-size: 0.8rem" id="service-select" class="persistent" onchange="toggleServiceFields()">
          <option value="openai">OpenAI</span></option>
<!--          <option value="amazon">Amazon Bedrock</option> -->
          <option value="local">Local</option>
    </select>
    <hr />
        <!-- OpenAI API Key Field -->
          <div id="openai-fields">
          <label for='api-key' style="font-size: 0.8rem">OpenAI <a href="https://beta.openai.com/signup">API key</a>:</label>
    <input type="text" style="font-size: 0.8rem" size="22" placeholder="(OpenAI API key)" id="api-key" oninput="checkApiKey(event.target.value)"></input>
    <span id="valid-api-key"></span>
    <br />
          <label style="font-size: 0.8rem" for="language-model-openai">
            Language model:
          </label>
          <select style="font-size: 0.8rem" id="language-model-openai" class="persistent" name="language-model-openai-label">
            <option value="gpt-3.5-turbo">GPT 3.5</option>
            <option value="gpt-4" selected>GPT 4.0</option>
    </select>
	    </div>
        
        <!-- Amazon Bedrock Fields -->
        <div id="amazon-fields" style="display: none;">
          <label for='aws-access-key' style="font-size: 0.8rem">AWS Access Key ID:</label>
    <input type="text" style="font-size: 0.8rem" size="22" placeholder="AKIAxxxxxxxxxxxxxxxx" id="aws-access-key" class="persistent"></input>
    <br />
    <label for='aws-secret-key' style="font-size: 0.8rem">AWS Secret Access Key:</label>
    <input type="text" style="font-size: 0.8rem" size="22" placeholder="(Secret Access Key)" id="aws-secret-key" class="persistent"></input>
    <br />
          <label style="font-size: 0.8rem" for="language-model-amazon">
            Language model:
          </label>
          <select style="font-size: 0.8rem" id="language-model-amazon" name="language-model-amazon-label">
            <option value="claude-2.1" selected>Claude 2.1</option>
          </select>
        </div>

        <!-- Local Fields -->
    <div id="local-fields" style="display: none; font-size: 0.8rem">
    Use this option if you are running a local language model. We currently support <a href="https://ollama.ai/">Ollama</a>.
    <br />
          <label for='local-ip' style="font-size: 0.8rem">IP Address:</label>
          <input type="text" style="font-size: 0.8rem" size="22" placeholder="localhost" id="local-ip" class="persistent" value="localhost"></input>
          <label for='local-port' style="font-size: 0.8rem">Port:</label>
    <input type="number" style="font-size: 0.8rem" size="22" placeholder="11434" id="local-port" class="persistent" value="11434"></input>
    <br />
    <div id="install-models-message" style="display:none;">
      Server not found or no language models installed.<br />
      Install language models as in <span style="background-color:rgb(220 220 220);"><code>ollama pull codellama:34b-python</code></span>.
    </div>

    <br />
    <div id="local-models-list">
          <label style="font-size: 0.8rem" for="language-model-local">
            Language model:
          </label>
    <span style="font-size: 0.8rem">
    </span>
    <div id="language-local-models"></div>
    </div>
        </div>
	  <br />
	  <B style="font-size:0.8rem">Proposed optimizations</B><BR />
	  <div>
	    <input type="radio" name="optimize-radio" id="optimize-performance" value="performance" class="persistent" checked>
	    <label style="font-size: 0.8rem" for="optimize-performance">
	      Optimize runtime performance
	    </label>
	  </div>
	  <div>
	    <input type="radio" name="optimize-radio" id="optimize-memory" class="persistent" value="memory">
	    <label style="font-size: 0.8rem" for="optimize-memory">
	      Optimize memory efficiency
	    </label>
	  </div>
	  <input type="checkbox" id="use-gpu-checkbox" name="use-gpu-checkbox-label" class="persistent" >
	  <!-- onclick="try { window.localStorage.setItem('scalene-gpu-checkbox', document.getElementById('use-gpu-checkbox').checked); } catch {}" -->
	  <label style="font-size: 0.8rem" for="use-gpu-checkbox" class="persistent">
	    Include GPU optimizations
	  </label>
	  <br />
	  <font style="font-size: 0.8rem">
	    Click on an explosion (&#128165;) to see proposed optimizations for a region of code,<br />
	    or on a lightning bolt (&#9889;) to propose optimizations for a specific line.<br />
	    Click again to generate a different one.<br />
	    <em>Note that optimizations are AI-generated and may not be correct.</em>
	    <br />
	  </font>
	  <br />
	  </details>
	</div>
    <div id="profile">
    </div>
    <script type="text/javascript">
      /// <reference types="aws-sdk" />

function vsNavigate(filename, lineno) {
    // If we are in VS Code, clicking on a line number in Scalene's web UI will navigate to that line in the source code.
    try {
	const vscode = acquireVsCodeApi();
        vscode.postMessage({
            command: 'jumpToLine',
            filePath: filename,
            lineNumber: lineno
        });
    } catch {
    }
    
}

const RightTriangle = "&#9658"; // right-facing triangle symbol (collapsed view)
const DownTriangle = "&#9660"; // downward-facing triangle symbol (expanded view)
const Lightning = "&#9889;"; // lightning bolt (for optimizing a line)
const Explosion = "&#128165;"; // explosion (for optimizing a region)
const WhiteLightning = `<span style="opacity:0">${Lightning}</span>`; // invisible but same width as lightning bolt
const WhiteExplosion = `<span style="opacity:0">${Explosion}</span>`; // invisible but same width as lightning bolt
const maxLinesPerRegion = 50; // Only show regions that are no more than this many lines.

let showedExplosion = {}; // Used so we only show one explosion per region.

function unescapeUnicode(s) {
  return s.replace(/\\u([\dA-F]{4})/gi, function (match, p1) {
    return String.fromCharCode(parseInt(p1, 16));
  });
}

async function tryApi(apiKey) {
  const response = await fetch("https://api.openai.com/v1/completions", {
    method: "GET",
    headers: {
	  "Content-Type": "application/json",
      Authorization: `Bearer ${apiKey}`,
    }
  });
    return response;
}

async function isValidApiKey(apiKey) {
    const response = await tryApi(apiKey);
    const data = await response.json();
    if (data.error && (data.error.code in { "invalid_api_key" : true,
					    "invalid_request_error" : true,
					    "model_not_found" : true,
					    "insufficient_quota" : true })) {
	return false;
    } else {
	return true;
    }
}

function checkApiKey(apiKey) {
    (async () => {
	try {	
	    window.localStorage.setItem("scalene-api-key", apiKey);
	} catch {
	}
    // If the API key is empty, clear the status indicator.
    if (apiKey.length === 0) {
      document.getElementById("valid-api-key").innerHTML = "";
      return;
    }
	const isValid = await isValidApiKey(apiKey);
	if (!isValid) {
	    document.getElementById("valid-api-key").innerHTML = "&#10005;";
	} else {
	    document.getElementById("valid-api-key").innerHTML = "&check;";
	}
    })();
}

function extractCode(text) {
  /**
  * Extracts code block from the given completion text.
  *
  * @param {string} text - A string containing text and other data.
  * @returns {string} Extracted code block from the completion object.
  */
    if (!text) {
	return text;
    }
  const lines = text.split('\n');
  let i = 0;
  while (i < lines.length && lines[i].trim() === '') {
    i++;
  }
    const first_line = lines[i].trim();
  let code_block;
  if (first_line === '```') {
    code_block = text.slice(3);
  } else if (first_line.startsWith('```')) {
    const word = first_line.slice(3).trim();
    if (word.length > 0 && !word.includes(' ')) {
      code_block = text.slice(first_line.length);
    } else {
      code_block = text;
    }
  } else {
    code_block = text;
  }
  const end_index = code_block.indexOf('```');
  if (end_index !== -1) {
    code_block = code_block.slice(0, end_index);
  }
  return code_block;
}

async function sendPromptToOpenAI(prompt, len, apiKey) {
    const endpoint = "https://api.openai.com/v1/chat/completions";
    const model = document.getElementById('language-model-openai').value;
    
    const body = JSON.stringify({
	model: model,
	messages: [
	    {
		role: 'system',
		content: 'You are a Python programming assistant who ONLY responds with blocks of commented, optimized code. You never respond with text. Just code, starting with ``` and ending with ```.'
	    },
	    {
		role: 'user',
		content: prompt
	    }
	],
	temperature: 0.3,
	frequency_penalty: 0,
	presence_penalty: 0,
	user: "scalene-user"
    });

    console.log(body);
    
    const response = await fetch(endpoint, {
	method: "POST",
	headers: {
	    "Content-Type": "application/json",
	    Authorization: `Bearer ${apiKey}`,
	},
	body: body,
    });

    const data = await response.json();
    if (data.error) {
	if (data.error.code in { "invalid_request_error" : true,
				 "model_not_found" : true,
				 "insufficient_quota" : true }) {
	    if ((data.error.code === "model_not_found") && (model === "gpt-4")) {
		// Technically, model_not_found applies only for GPT-4.0
		// if an account has not been funded with at least $1.
		alert("You either need to add funds to your OpenAI account to use this feature, or you need to switch to GPT-3.5 if you are using free credits.");
	    } else {
		alert("You need to add funds to your OpenAI account to use this feature.");
	    }
	    return "";
	}
    }
    try {
	console.log(`Debugging info: Retrieved ${JSON.stringify(data.choices[0], null, 4)}`);
    } catch {
	console.log(`Debugging info: Failed to retrieve data.choices from the server. data = ${JSON.stringify(data)}`);
    }
    
    try {
	return data.choices[0].message.content.replace(/^\s*[\r\n]/gm, "");
    } catch {
	// return "# Query failed. See JavaScript console (in Chrome: View > Developer > JavaScript Console) for more info.\n";
	return "# Query failed. See JavaScript console (in Chrome: View > Developer > JavaScript Console) for more info.\n";
    }
}

async function sendPromptToAmazon(prompt, len) {
    const serviceName = "bedrock";
    const region = "us-west-2";
    const modelId = "anthropic.claude-v2";
    const endpoint = `https://${serviceName}-runtime.${region}.amazonaws.com/model/${modelId}/invoke`
    // const model = document.getElementById('language-model-amazon').value;
    
    const body = JSON.stringify({
	prompt: `Human: ${prompt}\n\nAssistant:\n`,
        "max_tokens_to_sample" : 2048,
        "temperature": 0,
        "top_k": 250,
        "top_p": 1,
        "stop_sequences": [
            "\n\nHuman:"
        ],
        "anthropic_version": "bedrock-2023-05-31"
    });

    console.log(body);

    var bedrockruntime = new AWS.BedrockRuntime();
    bedrockruntime.invokeModel(body, function (err, data) {
	if (err) console.log(err, err.stack); // an error occurred
	else     console.log(data);           // successful response
    });
    const response = await fetch(endpoint, {
	method: "POST",
	headers: {
	    "Content-Type": "application/json",
//	    Authorization: `Bearer ${apiKey}`,
	},
	body: body,
    });

    const data = await response.json();
    console.log(data);
    try {
	console.log(`Debugging info: Retrieved ${JSON.stringify(data.choices[0], null, 4)}`);
    } catch {
	console.log(`Debugging info: Failed to retrieve data.choices from the server. data = ${JSON.stringify(data)}`);
    }
    
    try {
	return data.choices[0].message.content.replace(/^\s*[\r\n]/gm, "");
    } catch {
	// return "# Query failed. See JavaScript console (in Chrome: View > Developer > JavaScript Console) for more info.\n";
	return "# Query failed. See JavaScript console (in Chrome: View > Developer > JavaScript Console) for more info.\n";
    }
}


async function sendPromptToOllama(prompt, len, model, ipAddr, portNum) {
    const url = `http://${ipAddr}:${portNum}/api/chat`; 
    const headers = { 'Content-Type': 'application/json' };
    const body = JSON.stringify({
	model: model,
	messages: [
	    {
		role: 'system',
		content: 'You are a Python programming assistant who ONLY responds with blocks of commented, optimized code. You never respond with text. Just code, in a JSON object with the key "code".'
	    },
	    {
		role: 'user',
		content: prompt
	    }
	],
	format: "json",
	temperature: 0.3,
	frequency_penalty: 0,
	presence_penalty: 0,
	user: "scalene-user"
    });

    console.log(body);

    let done = false;
    let responseAggregated = "";
    let retried = 0;
    const retries = 3;
    
    while (!done) {

        if (retried >= retries) {
	    return {};
        }
	
        try {
            const response = await fetch(url, {
                method: 'POST',
                headers: headers,
                body: body
            });
	    
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }

            const text = await response.text();
	    const responses = text.split('\n');
	    for (const resp of responses) {
                const responseJson = JSON.parse(resp);
                if (responseJson.message && responseJson.message.content) {
		    responseAggregated += responseJson.message.content;
                }
		
                if (responseJson.done) {
		    done = true;
		    break;
                }
	    }
        } catch (error) {
            console.log(`Error: ${error}`);
            retried++;
        }
    }

    console.log(responseAggregated);
    try {
	return responseAggregated; // data.choices[0].message.content.replace(/^\s*[\r\n]/gm, "");
    } catch {
	// return "# Query failed. See JavaScript console (in Chrome: View > Developer > JavaScript Console) for more info.\n";
	return "# Query failed. See JavaScript console (in Chrome: View > Developer > JavaScript Console) for more info.\n";
    }
}


function countSpaces(str) {
  // Use a regular expression to match any whitespace character at the start of the string
  const match = str.match(/^\s+/);

  // If there was a match, return the length of the match
  if (match) {
    return match[0].length;
  }

  // Otherwise, return 0
  return 0;
}

async function optimizeCode(imports, code, context) {
    // Tailor prompt to request GPU optimizations or not.
    const useGPUs = document.getElementById('use-gpu-checkbox').checked; // globalThis.profile.gpu;
    const useGPUstring = useGPUs ? " or the GPU " : " ";
    // Check for a valid API key.
    // TODO: Add checks for Amazon / local
    let apiKey = "";
    if (document.getElementById("service-select").value === "openai") {
	apiKey = document.getElementById("api-key").value;
	if (!apiKey) {
	    alert(
		"To activate proposed optimizations, enter an OpenAI API key in AI optimization options."
	    );
	    document.getElementById("ai-optimization-options").open = true;
	    return '';
	}
    }
    // If the code to be optimized is just one line of code, say so.
    let lineOf = " ";
    if (code.split("\n").length <= 2) {
	lineOf = " line of ";
    }

    let libraries = 'import sklearn';
    if (useGPUs) {
	// Suggest cupy if we are using the GPU.
	libraries += '\nimport cupy';
    } else {
	// Suggest numpy otherwise.
	libraries += '\nimport numpy as np';
    }
    
    // Construct the prompt.

    const optimizePerformancePrompt = `Optimize the following${lineOf}Python code:\n\n${context}\n\n# Start of code\n\n${code}\n\n# End of code\n\nRewrite the above Python code only from "Start of code" to "End of code", to make it more efficient WITHOUT CHANGING ITS RESULTS. Assume the code has already executed all these imports; do NOT include them in the optimized code:\n\n${imports}\n\nUse native libraries if that would make it faster than pure Python. Consider using the following other libraries, if appropriate:\n\n${libraries}\n\nYour output should only consist of valid Python code. Output the resulting Python with brief explanations only included as comments prefaced with #. Include a detailed explanatory comment before the code, starting with the text "# Proposed optimization:". Make the code as clear and simple as possible, while also making it as fast and memory-efficient as possible. Use vectorized operations${useGPUstring}whenever it would substantially increase performance, and quantify the speedup in terms of orders of magnitude. Eliminate as many for loops, while loops, and list or dict comprehensions as possible, replacing them with vectorized equivalents. If the performance is not likely to increase, leave the code unchanged. Fix any errors in the optimized code. Optimized${lineOf}code:`;

    const context_ollama = "";
    const optimizePerformancePrompt_ollama_prev = `Optimize the following${lineOf}Python code:\n\n${context_ollama}\n\n# Start of code\n\n${code}\n\n# End of code\n\nRewrite the above Python code only from "Start of code" to "End of code", to make it more efficient WITHOUT CHANGING ITS RESULTS. Only output your result in JSON, with the optimized code in "code". Optimized${lineOf}code:`;

    const optimizePerformancePrompt_ollama = `Rewrite the following Python code to make it run faster. Use vectorization if possible, eliminating as many loops as possible. Try to reduce computational complexity of operations. Only output the optimized code in JSON with the key 'code'. Original code: ${code}. Optimized code:`
    
    const pure_optimizePerformancePrompt = `Optimize the following${lineOf}Python code:\n\n${context}\n\n# Start of code\n\n${code}\n\n# End of code\n\nRewrite the above Python code only from "Start of code" to "End of code", to make it more efficient WITHOUT CHANGING ITS RESULTS. Assume the code has already executed all these imports; do NOT include them in the optimized code:\n\n${imports}\n\nONLY USE PURE PYTHON.\n\nYour output should only consist of valid Python code. Output the resulting Python with brief explanations only included as comments prefaced with #. Include a detailed explanatory comment before the code, starting with the text "# Proposed optimization:". Make the code as clear and simple as possible, while also making it as fast and memory-efficient as possible. If the performance is not likely to increase, leave the code unchanged. Fix any errors in the optimized code. Optimized${lineOf}code:`

    const memoryEfficiencyPrompt = `Optimize the following${lineOf} Python code:\n\n${context}\n\n# Start of code\n\n${code}\n\n\n# End of code\n\nRewrite the above Python code only from "Start of code" to "End of code", to make it more memory-efficient WITHOUT CHANGING ITS RESULTS. Assume the code has already executed all these imports; do NOT include them in the optimized code:\n\n${imports}\n\nUse native libraries if that would make it more space efficient than pure Python. Consider using the following other libraries, if appropriate:\n\n${libraries}\n\nYour output should only consist of valid Python code. Output the resulting Python with brief explanations only included as comments prefaced with #. Include a detailed explanatory comment before the code, starting with the text "# Proposed optimization:". Make the code as clear and simple as possible, while also making it as fast and memory-efficient as possible. Use native libraries whenever possible to reduce memory consumption; invoke del on variables and array elements as soon as it is safe to do so. If the memory consumption is not likely to be reduced, leave the code unchanged. Fix any errors in the optimized code. Optimized${lineOf}code:`

    const optimizePerf = document.getElementById('optimize-performance').checked;

    let prompt;
    if (optimizePerf) {
 	prompt = optimizePerformancePrompt;
    } else {
	prompt = memoryEfficiencyPrompt;
    }
    
    // const prompt = `Below is some Python code to optimize, from "Start of code" to "End of code":\n\n# Start of code\n\n${code}\n\n# End of code\n\nRewrite the above Python code to make it more efficient without changing the results. Assume the code has already executed these imports. Do NOT include them in the optimized code:\n\n${imports}\n\nUse fast native libraries if that would make it faster than pure Python. Your output should only consist of valid Python code. Output the resulting Python with brief explanations only included as comments prefaced with #. Include a detailed explanatory comment before the code, starting with the text "# Proposed optimization:". Make the code as clear and simple as possible, while also making it as fast and memory-efficient as possible. Use vectorized operations${useGPUstring}whenever it would substantially increase performance, and quantify the speedup in terms of orders of magnitude. If the performance is not likely to increase, leave the code unchanged. Check carefully by generating inputs to see that the output is identical for both the original and optimized versions. Correctly-optimized code:`;

  // const prev_prompt =  `Below is some Python code to optimize:\n\n${code}\n\nRewrite the above Python code to make it more efficient while keeping the same semantics. Use fast native libraries if that would make it faster than pure Python. Your output should only consist of valid Python code. Output only the resulting Python with brief explanations only included as comments prefaced with #. Include a detailed explanatory comment before the code, starting with the text "# Proposed optimization:". Make the code as clear and simple as possible, while also making it as fast and memory-efficient as possible. Use vectorized operations or the GPU whenever it would substantially increase performance, and try to quantify the speedup in terms of orders of magnitude. If the performance is not likely to increase, leave the code unchanged. Your output should only consist of legal Python code. Format all comments to be less than 40 columns wide:\n\n`;

    // Use number of words in the original code as a proxy for the number of tokens.
    const numWords = (code.match(/\b\w+\b/g)).length;

    switch (document.getElementById('service-select').value) {
    case "openai":
	{
	    console.log(prompt);
	    const result = await sendPromptToOpenAI(prompt, Math.max(numWords * 4, 500), apiKey);
	    return extractCode(result);
	}
    case "local":
	{
	    console.log("Running " + document.getElementById('service-select').value);
	    console.log(optimizePerformancePrompt_ollama);
	    const result = await sendPromptToOllama(optimizePerformancePrompt_ollama, Math.max(numWords * 4, 500), document.getElementById('language-model-local').value, document.getElementById('local-ip').value, document.getElementById('local-port').value);
	    return JSON.parse(result)["code"];
	}
    case "amazon":
	{
	    console.log("Running " + document.getElementById('service-select').value);
	    console.log(optimizePerformancePrompt_ollama);
	    const result = await sendPromptToAmazon(optimizePerformancePrompt_ollama, Math.max(numWords * 4, 500));
	    console.log(document.getElementById('service-select').value + " not yet supported.");
	    return '';
	}
    }
}

function proposeOptimizationRegion(filename, file_number, lineno) {
  proposeOptimization(filename, file_number, lineno, { regions: true });
}

function proposeOptimizationLine(filename, file_number, lineno) {
  proposeOptimization(filename, file_number, lineno, { regions: false });
}

function proposeOptimization(filename, file_number, lineno, params) {
    filename = unescape(filename)
  const useRegion = params["regions"];
  const prof = globalThis.profile;
  const this_file = prof.files[filename].lines;
  const imports = prof.files[filename].imports.join("\n");
  const start_region_line = this_file[lineno - 1]["start_region_line"];
  const end_region_line = this_file[lineno - 1]["end_region_line"];
    let context; 
  const code_line = this_file[lineno - 1]["line"];
  let code_region;
  if (useRegion) {
    code_region = this_file
      .slice(start_region_line - 1, end_region_line)
      .map((e) => e["line"])
      .join("");
    context = this_file.slice(Math.max(0, start_region_line - 10), Math.min(start_region_line - 1, this_file.length))
	  .map((e) => e["line"])
	  .join("");
  } else {
    code_region = code_line;
    context = this_file.slice(Math.max(0, lineno - 10), Math.min(lineno - 1, this_file.length))
	  .map((e) => e["line"])
	  .join("");
  }
  // Count the number of leading spaces to match indentation level on output
  let leadingSpaceCount = countSpaces(code_line) + 3; // including the lightning bolt and explosion
  let indent =
    WhiteLightning + WhiteExplosion + "&nbsp;".repeat(leadingSpaceCount - 1);
  const elt = document.getElementById(`code-${file_number}-${lineno}`);
    (async () => {
	// TODO: check Amazon credentials
	const service = document.getElementById('service-select').value;
	if (service === "openai") {
	    const isValid = await isValidApiKey(
		document.getElementById("api-key").value
	    );
	    if (!isValid) {
		alert("You must enter a valid OpenAI API key to activate proposed optimizations.");
		document.getElementById("ai-optimization-options").open = true;
		return;
	    }
	}
	if (service == "local") {
	    if (document.getElementById('local-models-list').style.display === "none") {
		// No service was found.
		alert("You must be connected to a running Ollama server to activate proposed optimizations.");
		document.getElementById("ai-optimization-options").open = true;
		return;
	    }
	}
    elt.innerHTML = `<em>${indent}working...</em>`;
      let message = await optimizeCode(imports, code_region, context);
    if (!message) {
      elt.innerHTML = "";
      return;
    }
    // Canonicalize newlines
    message = message.replace(new RegExp("\r?\n", "g"), "\n");
    // Indent every line and format it
    const formattedCode = message
      .split("\n")
      .map(
        (line) =>
          indent + Prism.highlight(line, Prism.languages.python, "python")
      )
	  .join("<br />");
      // Display the proposed optimization, with click-to-copy functionality.
      elt.innerHTML = `<hr><span title="click to copy" style="cursor: copy" id="opt-${file_number}-${lineno}">${formattedCode}</span>`;
      thisElt = document.getElementById(`opt-${file_number}-${lineno}`);
      thisElt.addEventListener("click",
			       async (e) => {
				   await copyOnClick(e, message);
				   // After copying, briefly change the cursor back to the default to provide some visual feedback..
				   thisElt.style = "cursor: auto";
				   await new Promise(resolve => setTimeout(resolve, 125));
				   thisElt.style = "cursor: copy";
			       });
  })();
}

async function copyOnClick(event, message) {
    event.preventDefault();
    event.stopPropagation();
    await navigator.clipboard.writeText(message);
}

function memory_consumed_str(size_in_mb) {
  // Return a string corresponding to amount of memory consumed.
  let gigabytes = Math.floor(size_in_mb / 1024);
  let terabytes = Math.floor(gigabytes / 1024);
  if (terabytes > 0) {
    return `${(size_in_mb / 1048576).toFixed(3)} TB`;
  } else if (gigabytes > 0) {
    return `${(size_in_mb / 1024).toFixed(3)} GB`;
  } else {
    return `${size_in_mb.toFixed(3)} MB`;
  }
}

function time_consumed_str(time_in_ms) {
  let hours = Math.floor(time_in_ms / 3600000);
  let minutes = Math.floor((time_in_ms % 3600000) / 60000);
  let seconds = Math.floor((time_in_ms % 60000) / 1000);
  let hours_exact = time_in_ms / 3600000;
  let minutes_exact = (time_in_ms % 3600000) / 60000;
  let seconds_exact = (time_in_ms % 60000) / 1000;
  if (hours > 0) {
    return `${hours.toFixed(0)}h:${minutes_exact.toFixed(
      0
    )}m:${seconds_exact.toFixed(3)}s`;
  } else if (minutes >= 1) {
    return `${minutes.toFixed(0)}m:${seconds_exact.toFixed(3)}s`;
  } else if (seconds >= 1) {
    return `${seconds_exact.toFixed(3)}s`;
  } else {
    return `${time_in_ms.toFixed(3)}ms`;
  }
}

function makeBar(python, native, system, params) {
  return {
    $schema: "https://vega.github.io/schema/vega-lite/v5.json",
    config: {
      view: {
        stroke: "transparent",
      },
    },
    autosize: {
      contains: "padding",
    },
      width: params.width,
      height: params.height,
    padding: 0,
    data: {
      values: [
        {
          x: 0,
          y: python.toFixed(1),
          c: "(Python) " + python.toFixed(1) + "%",
          d: python.toFixed(0) + "%",
        },
        {
          x: 0,
          y: native.toFixed(1),
          c: "(native) " + native.toFixed(1) + "%",
          d: native.toFixed(0) + "%",
        },
        {
          x: 0,
          y: system.toFixed(1),
          c: "(system) " + system.toFixed(1) + "%",
          d: system.toFixed(0) + "%",
        },
      ],
    },
    layer: [
      {
        mark: { type: "bar" },
        encoding: {
          x: {
            aggregate: "sum",
            field: "y",
            axis: false,
            scale: { domain: [0, 100] },
          },
          color: {
            field: "c",
            type: "nominal",
            legend: false,
            scale: { range: ["darkblue", "#6495ED", "blue"] },
          },
          tooltip: [{ field: "c", type: "nominal", title: "time" }],
        },
      },
      /*	  ,
      {
          mark: {
              type: "text",
              opacity: 1.0,
              color: "white",
              align: "right",
              limit: 50,
          },
          encoding: {
              x: { type: "quantitative", field: "y" },
              text: {
		  field: "d",
		  bandPosition: 0.5,
		  condition: { test: `datum['y'] < 20`, value: "" },
              },
          },
	  },
	  */
    ],
  };
}

function makeGPUPie(util) {
  return {
    $schema: "https://vega.github.io/schema/vega-lite/v5.json",
    config: {
      view: {
        stroke: "transparent",
      },
    },
    autosize: {
      contains: "padding",
    },
      width: 30,
      height: 20,
    padding: 0,
    data: {
      values: [
        {
          category: 1,
          value: util.toFixed(1),
          c: "in use: " + util.toFixed(1) + "%",
        },
      ],
    },
    mark: "arc",
    encoding: {
      theta: {
        field: "value",
        type: "quantitative",
        scale: { domain: [0, 100] },
      },
      color: {
        field: "c",
        type: "nominal",
        legend: false,
        scale: { range: ["goldenrod", "#f4e6c2"] },
      },
      tooltip: [{ field: "c", type: "nominal", title: "GPU" }],
    },
  };
}

function makeMemoryPie(native_mem, python_mem, params) {
  return {
    $schema: "https://vega.github.io/schema/vega-lite/v5.json",
      width: params.width,
    height: 20,
    padding: 0,
    data: {
      values: [
        {
          category: 1,
          value: native_mem.toFixed(1),
          c: "native: " + native_mem.toFixed(1) + "%",
        },
        {
          category: 2,
          value: python_mem.toFixed(1),
          c: "Python: " + python_mem.toFixed(1) + "%",
        },
      ],
    },
    mark: "arc",
    encoding: {
      theta: {
        field: "value",
        type: "quantitative",
        scale: { domain: [0, 100] },
      },
      color: {
        field: "c",
        type: "nominal",
        legend: false,
        scale: { range: ["darkgreen", "#50C878"] },
      },
      tooltip: [{ field: "c", type: "nominal", title: "memory" }],
    },
  };
}

function makeMemoryBar(memory, title, python_percent, total, color, params) {
  return {
    $schema: "https://vega.github.io/schema/vega-lite/v5.json",
    config: {
      view: {
        stroke: "transparent",
      },
    },
    autosize: {
      contains: "padding",
    },
      width: params.width,
      height: params.height,
    padding: 0,
    data: {
      values: [
        {
          x: 0,
          y: python_percent * memory,
          c: "(Python) " + memory_consumed_str(python_percent * memory),
        },
        {
          x: 0,
          y: (1.0 - python_percent) * memory,
          c: "(native) " + memory_consumed_str((1.0 - python_percent) * memory),
        },
      ],
    },
    mark: { type: "bar" },
    encoding: {
      x: {
        aggregate: "sum",
        field: "y",
        axis: false,
        scale: { domain: [0, total] },
      },
      color: {
        field: "c",
        type: "nominal",
        legend: false,
        scale: { range: [color, "#50C878", "green"] },
      },
      tooltip: [{ field: "c", type: "nominal", title: title }],
    },
  };
}

function makeSparkline(
  samples,
  max_x,
  max_y,
    leak_velocity = 0,
    params
) {
  const values = samples.map((v, i) => {
    let leak_str = "";
    if (leak_velocity != 0) {
      leak_str = `; possible leak (${memory_consumed_str(leak_velocity)}/s)`;
    }
    return {
      x: v[0],
      y: v[1],
      y_text:
        memory_consumed_str(v[1]) +
        " (@ " +
        time_consumed_str(v[0] / 1e6) +
        ")" +
        leak_str,
    };
  });
  let leak_info = "";
  if (leak_velocity != 0) {
    leak_info = "possible leak";
      params.height -= 10; // FIXME should be actual height of font
  }

  const strokeWidth = 1; // 0.25;
  return {
    $schema: "https://vega.github.io/schema/vega-lite/v5.json",
    data: { values: values },
    width: params.width,
    height: params.height,
    padding: 0,
    title: {
      text: leak_info,
      baseline: "line-bottom",
      color: "red",
      offset: 0,
      lineHeight: 10,
      orient: "bottom",
      fontStyle: "italic",
    },
    encoding: {
      x: {
        field: "x",
        type: "quantitative",
        title: "",
        axis: {
          tickCount: 10,
          tickSize: 0,
          labelExpr: "",
        },
        scale: {
          domain: [0, max_x],
        },
      },
    },
    layer: [
      {
        encoding: {
          y: {
            field: "y",
            type: "quantitative",
            axis: null,
            scale: {
              domain: [0, max_y],
            },
          },
          color: {
            field: "c",
            type: "nominal",
            legend: null,
            scale: {
              range: ["darkgreen"],
            },
          },
        },

        layer: [
          { mark: "line" },
          {
            transform: [{ filter: { param: "hover", empty: false } }],
            mark: "point",
          },
        ],
      },

      {
        mark: "rule",
        encoding: {
          opacity: {
            condition: { value: 0.3, param: "hover", empty: false },
            value: 0,
          },
          tooltip: [{ field: "y_text", type: "nominal", title: "memory" }],
        },
        params: [
          {
            name: "hover",
            select: {
              type: "point",
              fields: ["y"],
              nearest: true,
              on: "mousemove",
            },
          },
        ],
      },
    ],
  };
}

const CPUColor = "blue";
const MemoryColor = "green";
const CopyColor = "goldenrod";
let columns = [];

function makeTableHeader(fname, gpu, memory, params) {
  let tableTitle;
  if (params["functions"]) {
    tableTitle = "function profile";
  } else {
    tableTitle = "line profile";
  }
  columns = [
    {
      title: ["time", ""],
      color: CPUColor,
      width: 0,
      info: "Execution time (Python + native + system)",
    },
  ];
  if (memory) {
    columns = columns.concat([
      {
        title: ["memory", "average"],
        color: MemoryColor,
        width: 0,
        info: "Average amount of memory allocated by line / function",
      },
      {
        title: ["memory", "peak"],
        color: MemoryColor,
        width: 0,
        info: "Peak amount of memory allocated by line / function",
      },
      {
        title: ["memory", "timeline"],
        color: MemoryColor,
        width: 0,
        info: "Memory footprint over time",
      },
      {
        title: ["memory", "activity"],
        color: MemoryColor,
        width: 0,
        info: "% of bytes allocated by line / function over total bytes allocated in file",
      },
      {
        title: ["copy", ""],
        color: CopyColor,
        width: 0,
        info: "Rate of copying memory",
      },
    ]);
  }
  if (gpu) {
    columns.push({
      title: ["gpu", "util."],
      color: CopyColor,
      width: 0,
      info: "% utilization of the GPU by line / function (may be inaccurate if GPU is not dedicated)",
    });
    columns.push({
      title: ["gpu", "memory"],
      color: CopyColor,
      width: 0,
      info: "Peak GPU memory allocated by line / function (may be inaccurate if GPU is not dedicated)",
    });
  }
  columns.push({ title: ["", ""], color: "black", width: 100 });
  let s = "";
  s += '<thead class="thead-light">';
  s += '<tr data-sort-method="thead">';
  for (const col of columns) {
      s += `<th class="F${escape(fname)}-nonline"><font style="font-variant: small-caps; text-decoration: underline; width:${col.width}" color=${col.color}>`;
    if (col.info) {
      s += `<a style="cursor:pointer;" title="${col.info}">${col.title[0]}</a>`;
    } else {
      s += `<a style="cursor:pointer;">${col.title[0]}</a>`;
    }
    s += "</font>&nbsp;&nbsp;</th>";
  }
  let id;
  if (params["functions"]) {
    id = "functionProfile";
  } else {
    id = "lineProfile";
  }
  s += `<th id=${
    escape(fname) + "-" + id
  } style="width:10000"><font style="font-variant: small-caps; text-decoration: underline">${tableTitle}</font><font style="font-size:small; font-style: italic">&nbsp; (click to reset order)</font></th>`;
  s += "</tr>";
  s += '<tr data-sort-method="thead">';
  for (const col of columns) {
    s += `<th style="width:${col.width}"><em><font style="font-size: small" color=${col.color}>${col.title[1]}</font></em></th>`;
  }
  s += `<th><code>${fname}</code></th></tr>`;
  s += "</thead>";
  return s;
}

function hideEmptyProfiles() {
  const elts = document.getElementsByClassName("empty-profile");
  for (elt of elts) {
    s = elt.style;
    s.display = "none";
  }
}

function toggleReduced() {
  const elts = document.getElementsByClassName("empty-profile");
  for (elt of elts) {
    s = elt.style;
    if (s.display == "") {
      s.display = "none";
    } else {
      s.display = "";
    }
  }
}

function makeProfileLine(
  line,
  filename,
  file_number,
  prof,
  cpu_bars,
  memory_bars,
  memory_sparklines,
  memory_activity,
  gpu_pies,
  propose_optimizations
) {
  let total_time =
    line.n_cpu_percent_python + line.n_cpu_percent_c + line.n_sys_percent;
  let total_region_time = 0;
  let region_has_memory_results = 0;
  let region_has_gpu_results = 0;
  for (
    let lineno = line.start_region_line;
    lineno < line.end_region_line;
    lineno++
  ) {
    currline = prof["files"][filename]["lines"][lineno];
    total_region_time +=
      currline.n_cpu_percent_python +
      currline.n_cpu_percent_c +
      currline.n_sys_percent;
    region_has_memory_results +=
      currline.n_avg_mb +
      currline.n_peak_mb +
      currline.memory_samples.length +
      (currline.n_usage_fraction >= 0.01);
    region_has_gpu_results |= line.n_gpu_percent >= 1.0;
  }
    // Disable optimization proposals for low CPU runtime lines.

    // TODO: tailor prompt for memory optimization when that's the only inefficiency.
    // ALSO propose optimizations not just for execution time but also for memory usage.
  if (propose_optimizations) {
    if (total_time < 1.0 && line.start_region_line === line.end_region_line) {
      propose_optimizations = false;
    }
    if (line.start_region_line != line.end_region_line) {
      if (total_region_time < 1.0) {
        propose_optimizations = false;
      }
    }
  }
  const has_memory_results =
    line.n_avg_mb +
    line.n_peak_mb +
    line.memory_samples.length +
    (line.n_usage_fraction >= 0.01);
  const has_gpu_results = line.n_gpu_percent >= 1.0;
  const start_region_line = line.start_region_line;
  const end_region_line = line.end_region_line;
  // Only show the explosion (optimizing a whole region) once.
  let explosionString;
  let showExplosion;
  if (
    start_region_line === end_region_line ||
    [[start_region_line - 1, end_region_line]] in showedExplosion
  ) {
    explosionString = WhiteExplosion;
    showExplosion = false;
  } else {
    explosionString = Explosion;
    if (start_region_line && end_region_line) {
      showedExplosion[[start_region_line - 1, end_region_line]] = true;
      showExplosion = true;
    }
  }
  // If the region is too big, for some definition of "too big", don't show it.
  showExplosion &= end_region_line - start_region_line <= maxLinesPerRegion;

  let s = "";
  if (
    total_time ||
    has_memory_results ||
    has_gpu_results ||
    (showExplosion &&
      start_region_line != end_region_line &&
      (total_region_time >= 1.0 ||
        region_has_memory_results ||
        region_has_gpu_results))
  ) {
    s += "<tr>";
  } else {
    s += "<tr class='empty-profile'>";
  }
  const total_time_str = String(total_time.toFixed(1)).padStart(10, " ");
  s += `<td style="height: 20; width: 100; vertical-align: middle" align="left" data-sort='${total_time_str}'>`;
  s += `<span style="height: 20; width: 100; vertical-align: middle" id="cpu_bar${cpu_bars.length}"></span>`;
  if (total_time) {
    cpu_bars.push(
      makeBar(
        line.n_cpu_percent_python,
        line.n_cpu_percent_c,
          line.n_sys_percent,
	  { height: 20, width: 100 }
      )
    );
  } else {
    cpu_bars.push(null);
  }
  if (prof.memory) {
    s += `<td style="height: 20; width: 100; vertical-align: middle" align="left" data-sort='${String(
      line.n_avg_mb.toFixed(0)
    ).padStart(10, "0")}'>`;
    s += `<span style="height: 20; width: 100; vertical-align: middle" id="memory_bar${memory_bars.length}"></span>`;
    s += "</td>";
    if (line.n_avg_mb) {
      memory_bars.push(
        makeMemoryBar(
          line.n_avg_mb.toFixed(0),
          "average memory",
          parseFloat(line.n_python_fraction),
          prof.max_footprint_mb.toFixed(2),
            "darkgreen",
	    { height: 20, width: 100 }
        )
      );
    } else {
      memory_bars.push(null);
    }
    s += `<td style="height: 20; width: 100; vertical-align: middle" align="left" data-sort='${String(
      line.n_peak_mb.toFixed(0)
    ).padStart(10, "0")}'>`;
    s += `<span style="height: 20; width: 100; vertical-align: middle" id="memory_bar${memory_bars.length}"></span>`;
    if (line.n_peak_mb) {
      memory_bars.push(
        makeMemoryBar(
          line.n_peak_mb.toFixed(0),
          "peak memory",
          parseFloat(line.n_python_fraction),
          prof.max_footprint_mb.toFixed(2),
            "darkgreen",
	    { height: 20, width: 100 }
        )
      );
    } else {
      memory_bars.push(null);
    }
    s += "</td>";
    s += `<td style='vertical-align: middle; width: 100'><span style="height:20; width: 100; vertical-align: middle" id="memory_sparkline${memory_sparklines.length}"></span>`;
    s += "</td>";
    if (line.memory_samples.length > 0) {
      let leak_velocity = 0;
      if ("leaks" in prof.files[filename]) {
        if (line.lineno in prof.files[filename].leaks) {
          leak_velocity = prof.files[filename].leaks[line.lineno].velocity_mb_s;
        }
      }
      memory_sparklines.push(
        makeSparkline(
          line.memory_samples,
          prof.elapsed_time_sec * 1e9,
          prof.max_footprint_mb,
            leak_velocity,
	    {height: 20, width: 75 }
        )
      );
    } else {
      memory_sparklines.push(null);
    }
    s += '<td style="width: 100; vertical-align: middle" align="center">';
    if (line.n_usage_fraction >= 0.01) {
      s += `<span style="height: 20; width: 30; vertical-align: middle" id="memory_activity${memory_activity.length}"></span>`;
      memory_activity.push(
        makeMemoryPie(
          100 *
            line.n_usage_fraction *
            (1 - parseFloat(line.n_python_fraction)),
            100 * line.n_usage_fraction * parseFloat(line.n_python_fraction),
	    { width: 30 }
        )
      );
    } else {
      memory_activity.push(null);
    }
    //      s += `<font style="font-size: small">${String(
    //        (100 * line.n_usage_fraction).toFixed(0)
    //      ).padStart(10, " ")}%&nbsp;&nbsp;&nbsp;</font>`;
    s += "</td>";
    if (line.n_copy_mb_s < 1.0) {
      s += '<td style="width: 100"></td>';
    } else {
      s += `<td style="width: 100; vertical-align: middle" align="right"><font style="font-size: small" color="${CopyColor}">${line.n_copy_mb_s.toFixed(
        0
      )}&nbsp;&nbsp;&nbsp;</font></td>`;
    }
  }
  if (prof.gpu) {
    if (line.n_gpu_percent < 1.0) {
      s += '<td style="width: 100"></td>';
    } else {
      //	    s += `<td style="width: 100; vertical-align: middle" align="right"><font style="font-size: small" color="${CopyColor}">${line.n_gpu_percent.toFixed(0)}%</font></td>`;
      s += `<td style="width: 50; vertical-align: middle" align="right" data-sort="${line.n_gpu_percent}">`;
      s += `<span style="height: 20; width: 30; vertical-align: middle" id="gpu_pie${gpu_pies.length}"></span>`;
      s += "</td>";
      gpu_pies.push(makeGPUPie(line.n_gpu_percent));
    }
    if (true) {
      if (line.n_gpu_peak_memory_mb < 1.0 || line.n_gpu_percent < 1.0) {
        s += '<td style="width: 100"></td>';
      } else {
        s += `<td style="width: 100; vertical-align: middle" align="right"><font style="font-size: small" color="${CopyColor}">${line.n_gpu_peak_memory_mb.toFixed(
          0
        )}</font></td>`;
      }
    }
  }
  const empty_profile =
    total_time ||
    has_memory_results ||
    has_gpu_results ||
    end_region_line != start_region_line
      ? ""
      : "empty-profile";
    s += `<td align="right" class="dummy ${empty_profile}" style="vertical-align: middle; width: 50" data-sort="${line.lineno}"><span onclick="vsNavigate('${escape(filename)}',${line.lineno})"><font color="gray" style="font-size: 70%; vertical-align: middle" >${line.lineno}&nbsp;</font></span></td>`;

  const regionOptimizationString =
    propose_optimizations && showExplosion
      ? `${explosionString}&nbsp;`
      : `${WhiteExplosion}&nbsp;`;

    // Convert back any escaped Unicode.
  line.line = unescapeUnicode(line.line);

  const codeLine = Prism.highlight(line.line, Prism.languages.python, "python");
  s += `<td style="height:10" align="left" bgcolor="whitesmoke" style="vertical-align: middle" data-sort="${line.lineno}">`;
  if (propose_optimizations && showExplosion) {
      s += `<span style="vertical-align: middle; cursor: pointer" title="Propose an optimization for the entire region starting here." onclick="proposeOptimizationRegion('${escape(filename)}', ${file_number}, ${parseInt(
      line.lineno
    )}); event.preventDefault()">${regionOptimizationString}</span>`;
  } else {
    s += regionOptimizationString;
  }

  const lineOptimizationString = propose_optimizations
    ? `${Lightning}`
    : `${WhiteLightning}`;
  if (propose_optimizations) {
      s += `<span style="vertical-align: middle; cursor: pointer" title="Propose an optimization for this line." onclick="proposeOptimizationLine('${escape(filename)}', ${file_number}, ${parseInt(
      line.lineno
    )}); event.preventDefault()">${lineOptimizationString}</span>`;
  } else {
    s += lineOptimizationString;
  }
    s += `<pre style="height: 10; display: inline; white-space: pre-wrap; overflow-x: auto; border: 0px; vertical-align: middle"><code class="language-python ${empty_profile}">${codeLine}<span id="code-${file_number}-${line.lineno}" bgcolor="white"></span></code></pre></td>`;
  s += "</tr>";
  return s;
}

function buildAllocationMaps(prof, f) {
  let averageMallocs = {};
  let peakMallocs = {};
  for (const line of prof.files[f].lines) {
    const avg = parseFloat(line.n_avg_mb);
    if (!averageMallocs[avg]) {
      averageMallocs[avg] = [];
    }
    averageMallocs[avg].push(line.lineno);
    const peak = parseFloat(line.n_peak_mb);
    if (!peakMallocs[peak]) {
      peakMallocs[peak] = [];
    }
    peakMallocs[peak].push(line.lineno);
  }
  return [averageMallocs, peakMallocs];
}

// Track all profile ids so we can collapse and expand them en masse.
let allIDs = [];

function collapseAll() {
  for (const id of allIds) {
    collapseDisplay(id);
  }
}

function expandAll() {
  for (const id of allIds) {
    expandDisplay(id);
  }
}

function collapseDisplay(id) {
  const d = document.getElementById(`profile-${id}`);
  d.style.display = "none";
  document.getElementById(`button-${id}`).innerHTML = RightTriangle;
}

function expandDisplay(id) {
  const d = document.getElementById(`profile-${id}`);
  d.style.display = "block";
  document.getElementById(`button-${id}`).innerHTML = DownTriangle;
}

function toggleDisplay(id) {
  const d = document.getElementById(`profile-${id}`);
  if (d.style.display == "block") {
    d.style.display = "none";
    document.getElementById(`button-${id}`).innerHTML = RightTriangle;
  } else {
    d.style.display = "block";
    document.getElementById(`button-${id}`).innerHTML = DownTriangle;
  }
}

async function display(prof) {
    // Clear explosions.
  showedExplosion = {};
    // Restore the API key from local storage (if any).
    let old_key = '';
    old_key = window.localStorage.getItem("scalene-api-key");

    if (old_key) {
	document.getElementById("api-key").value = old_key;
	// Update the status.
	checkApiKey(old_key);
    }

    let selectedService = window.localStorage.getItem("scalene-service-select");
    if (selectedService) {
	document.getElementById("service-select").value = selectedService;
	toggleServiceFields();
    }
    
    // Restore the old GPU toggle from local storage (if any).
    const gpu_checkbox = document.getElementById('use-gpu-checkbox')
    old_gpu_checkbox = window.localStorage.getItem("use-gpu-checkbox");
    if (old_gpu_checkbox) {
	if (gpu_checkbox.checked.toString() != old_gpu_checkbox) {
	    gpu_checkbox.click();
	}
    } else {
	// Set the GPU checkbox on if the profile indicated the presence of a GPU.
	if (gpu_checkbox.checked != prof.gpu) {
	    gpu_checkbox.click();
	}
    }
  globalThis.profile = prof;
  let memory_sparklines = [];
  let memory_activity = [];
  let cpu_bars = [];
  let gpu_pies = [];
  let memory_bars = [];
  let tableID = 0;
  let s = "";
  s += '<span class="row justify-content-center">';
  s += '<span class="col-auto">';
  s += '<table width="50%" class="table text-center table-condensed">';
  s += "<tr>";
  s += `<td><font style="font-size: small"><b>Time:</b> <font color="darkblue">Python</font> | <font color="#6495ED">native</font> | <font color="blue">system</font><br /></font></td>`;
  s += '<td width="10"></td>';
  if (prof.memory) {
    s += `<td><font style="font-size: small"><b>Memory:</b> <font color="darkgreen">Python</font> | <font color="#50C878">native</font><br /></font></td>`;
    s += '<td width="10"></td>';
    s += '<td valign="middle" style="vertical-align: middle">';
    s += `<font style="font-size: small"><b>Memory timeline: </b>(max: ${memory_consumed_str(
      prof.max_footprint_mb
    )}, growth: ${prof.growth_rate.toFixed(1)}%)</font>`;
    s += "</td>";
  }
  s += "</tr>";
  s += "<tr>";
  s +=
    '<td height="10"><span style="height: 20; width: 200; vertical-align: middle" id="cpu_bar0"></span></td>';
  s += "<td></td>";
  if (prof.memory) {
    s +=
      '<td height="20"><span style="height: 20; width: 150; vertical-align: middle" id="memory_bar0"></span></td>';
    s += "<td></td>";
    s +=
      '<td align="left"><span style="vertical-align: middle" id="memory_sparkline0"></span></td>';
    memory_sparklines.push(
      makeSparkline(
        prof.samples,
        prof.elapsed_time_sec * 1e9,
        prof.max_footprint_mb,
        0,
          { height: 20, width: 200 }
      )
    );
  }
  s += "</tr>";

  // Compute overall usage.
  let cpu_python = 0;
  let cpu_native = 0;
  let cpu_system = 0;
  let mem_python = 0;
  let mem_native = 0;
  let max_alloc = 0;
  for (const f in prof.files) {
    let cp = 0;
    let cn = 0;
    let cs = 0;
    let mp = 0;
    for (const l in prof.files[f].lines) {
      const line = prof.files[f].lines[l];
      cp += line.n_cpu_percent_python;
      cn += line.n_cpu_percent_c;
      cs += line.n_sys_percent;
      mp += line.n_malloc_mb * line.n_python_fraction;
      max_alloc += line.n_malloc_mb;
    }
    cpu_python += cp;
    cpu_native += cn;
    cpu_system += cs;
    mem_python += mp;
  }
    cpu_bars.push(makeBar(cpu_python, cpu_native, cpu_system, { height: 20, width: 200 }));
  if (prof.memory) {
    memory_bars.push(
      makeMemoryBar(
        max_alloc,
        "memory",
        mem_python / max_alloc,
        max_alloc,
          "darkgreen",
	  { height: 20, width: 150 }
      )
    );
  }

    
  s += '<tr><td colspan="10">';
  s += `<span class="text-center"><font style="font-size: 90%; font-style: italic; font-color: darkgray">hover over bars to see breakdowns; click on <font style="font-variant:small-caps; text-decoration:underline">column headers</font> to sort.</font></span>`;
  s += "</td></tr>";
  s += "</table>";
  s += "</span>";
  s += "</span>";

  s +=
    '<br class="text-left"><span style="font-size: 80%; color: blue; cursor : pointer;" onClick="expandAll()">&nbsp;show all</span> | <span style="font-size: 80%; color: blue; cursor : pointer;" onClick="collapseAll()">hide all</span>';
  s += ` | <span style="font-size: 80%; color: blue" onClick="document.getElementById('reduce-checkbox').click()">only display profiled lines&nbsp;</span><input type="checkbox" id="reduce-checkbox" checked onClick="toggleReduced()" /></br>`;
  s += '<div class="container-fluid">';

  // Convert files to an array and sort it in descending order by percent of CPU time.
  let files = Object.entries(prof.files);
  files.sort((x, y) => {
    return y[1].percent_cpu_time - x[1].percent_cpu_time;
  });

  // Print profile for each file
  let fileIteration = 0;
  allIds = [];
  for (const ff of files) {
    const id = `file-${fileIteration}`;
    allIds.push(id);
      s += '<p class="text-left sticky-top bg-white bg-opacity-75" style="backdrop-filter: blur(2px);">';
    s += `<span id="button-${id}" title="Click to show or hide profile." style="cursor: pointer; color: blue" onClick="toggleDisplay('${id}')">`;
    s += `${DownTriangle}`;
    s += "</span>";
    s += `<font style="font-size: 90%"><code>${
      ff[0]
    }</code>: % of time = ${ff[1].percent_cpu_time.toFixed(
      1
    )}% (${time_consumed_str(
      (ff[1].percent_cpu_time / 100.0) * prof.elapsed_time_sec * 1e3
    )}) out of ${time_consumed_str(prof.elapsed_time_sec * 1e3)}.</font></p>`;
    s += `<div style="display: block" id="profile-${id}">`;
    s += `<table class="profile table table-hover table-condensed" id="table-${tableID}">`;
    tableID++;
      s += makeTableHeader(ff[0], prof.gpu, prof.memory, { functions: false });
    s += "<tbody>";
    // Print per-line profiles.
    let prevLineno = -1;
    for (const l in ff[1].lines) {
	const line = ff[1].lines[l];
	
      if (false) {
        // Disabling spacers
        // Add a space whenever we skip a line.
        if (line.lineno > prevLineno + 1) {
          s += "<tr>";
          for (let i = 0; i < columns.length; i++) {
            s += "<td></td>";
          }
          s += `<td class="F${
            escape(ff[0])
          }-blankline" style="line-height: 1px; background-color: lightgray" data-sort="${
            prevLineno + 1
          }">&nbsp;</td>`;
          s += "</tr>";
        }
      }
      prevLineno = line.lineno;
      s += makeProfileLine(
        line,
        ff[0],
        fileIteration,
        prof,
        cpu_bars,
        memory_bars,
        memory_sparklines,
        memory_activity,
        gpu_pies,
        true
      );
    }
    s += "</tbody>";
    s += "</table>";
    // Print out function summaries.
    if (prof.files[ff[0]].functions.length) {
      s += `<table class="profile table table-hover table-condensed" id="table-${tableID}">`;
	s += makeTableHeader(ff[0], prof.gpu, prof.memory, { functions: true });
      s += "<tbody>";
      tableID++;
      for (const l in prof.files[ff[0]].functions) {
        const line = prof.files[ff[0]].functions[l];
        s += makeProfileLine(
          line,
          ff[0],
          fileIteration,
          prof,
          cpu_bars,
          memory_bars,
          memory_sparklines,
          memory_activity,
          gpu_pies,
          false // no optimizations here
        );
      }
      s += "</table>";
    }
    s += "</div>";
    fileIteration++;
    // Insert empty lines between files.
    if (fileIteration < files.length) {
      s += "<hr>";
    }
  }
  s += "</div>";
  const p = document.getElementById("profile");
  p.innerHTML = s;

  // Logic for turning on and off the gray line separators.

  // If you click on any header to sort (except line profiles), turn gray lines off.
  for (const ff of files) {
      const allHeaders = document.getElementsByClassName(`F${escape(ff[0])}-nonline`);
    for (let i = 0; i < allHeaders.length; i++) {
      allHeaders[i].addEventListener("click", (e) => {
          const all = document.getElementsByClassName(`F${escape(ff[0])}-blankline`);
        for (let i = 0; i < all.length; i++) {
          all[i].style.display = "none";
        }
      });
    }
  }

  // If you click on the line profile header, and gray lines are off, turn them back on.
  for (const ff of files) {
    document
	  .getElementById(`${escape(ff[0])}-lineProfile`)
      .addEventListener("click", (e) => {
          const all = document.getElementsByClassName(`F${escape(ff[0])}-blankline`);
        for (let i = 0; i < all.length; i++) {
          if (all[i].style.display === "none") {
            all[i].style.display = "block";
          }
        }
      });
  }

  for (let i = 0; i < tableID; i++) {
    new Tablesort(document.getElementById(`table-${i}`), { ascending: true });
  }
  memory_sparklines.forEach((p, index) => {
    if (p) {
      (async () => {
        await vegaEmbed(`#memory_sparkline${index}`, p, {
          actions: false,
          renderer: "svg",
        });
      })();
    }
  });
  cpu_bars.forEach((p, index) => {
    if (p) {
	(async () => {
            await vegaEmbed(`#cpu_bar${index}`, p, { actions: false });
      })();
    }
  });
  gpu_pies.forEach((p, index) => {
    if (p) {
      (async () => {
        await vegaEmbed(`#gpu_pie${index}`, p, { actions: false });
      })();
    }
  });
  memory_activity.forEach((p, index) => {
    if (p) {
      (async () => {
        await vegaEmbed(`#memory_activity${index}`, p, { actions: false });
      })();
    }
  });
  memory_bars.forEach((p, index) => {
    if (p) {
      (async () => {
        await vegaEmbed(`#memory_bar${index}`, p, { actions: false });
      })();
    }
  });
  // Hide all empty profiles by default.
  hideEmptyProfiles();
  if (prof.program) {
    document.title = "Scalene - " + prof.program;
  } else {
    document.title = "Scalene";
  }
}

function load(profile) {
  (async () => {
    // let resp = await fetch(jsonFile);
    // let prof = await resp.json();
    await display(profile);
  })();
}

function loadFetch() {
  (async () => {
    let resp = await fetch("profile.json");
    let profile = await resp.json();
    load(profile);
  })();
}

function loadFile() {
  const input = document.getElementById("fileinput");
  const file = input.files[0];
  const fr = new FileReader();
  fr.onload = doSomething;
  fr.readAsText(file);
}

function doSomething(e) {
  let lines = e.target.result;
  const profile = JSON.parse(lines);
  load(profile);
}

function loadDemo() {
  load(example_profile);
}

// JavaScript function to toggle fields based on selected service
function toggleServiceFields() {
    let service = document.getElementById("service-select").value;
    window.localStorage.setItem("scalene-service-select", service);
    document.getElementById("openai-fields").style.display = (service === "openai") ? "block" : "none";
    document.getElementById("amazon-fields").style.display = (service === "amazon") ? "block" : "none";
    document.getElementById("local-fields").style.display = (service === "local") ? "block" : "none";
}

function revealInstallMessage()
{
    console.log("REVEAL MESSAGE");
    document.getElementById('install-models-message').style.display = "block";
    document.getElementById('local-models-list').style.display = "none";
    
}

async function fetchModelNames() {
  try {
      const local_ip = document.getElementById('local-ip').value;
      const local_port = document.getElementById('local-port').value;
      const response = await fetch(`http://${local_ip}:${local_port}/api/tags`);
      if (!response.ok) {
	  throw new Error(`HTTP error! status: ${response.status}`);
      }
      const data = await response.json();

      // Extracting the model names
      const modelNames = data.models.map(model => model.name);
      if (modelNames.length === 0) {
	  revealInstallMessage();
      }
      return modelNames;
  } catch (error) {
      console.error('Error fetching model names:', error);
      revealInstallMessage();
      return [];
  }
}

function createSelectElement(modelNames) {
  // Create the select element
  const select = document.createElement('select');
  select.style.fontSize = '0.8rem';
  select.id = 'language-model-local';
  select.className = 'persistent';
  select.name = 'language-model-local-label';

  // Add options to the select element
  modelNames.forEach(modelName => {
    const option = document.createElement('option');
    option.value = modelName;
      option.textContent = modelName;
      option.id = modelName;
      select.appendChild(option);
  });

  return select;
}

function replaceDivWithSelect() {
  fetchModelNames().then(modelNames => {
    // Create the select element with options
    const selectElement = createSelectElement(modelNames);

    // Find the div and replace its content with the select element
    const div = document.getElementById('language-local-models');
    if (div) {
      div.innerHTML = ''; // Clear existing content
      div.appendChild(selectElement);
    } else {
      console.error('Div with ID "language-local-models" not found.');
    }
      atLeastOneModel = true;
  });

}

// Call the function to replace the div with the select element
replaceDivWithSelect();

// Process all DOM elements in the class 'persistent', which saves their state in localStorage and restores them on load.
document.addEventListener("DOMContentLoaded", () => {
    const persistentElements = document.querySelectorAll('.persistent');

    // Restore state
    persistentElements.forEach(el => {
        const savedValue = localStorage.getItem(el.id);

        if (savedValue !== null) {
            switch(el.type) {
                case 'checkbox':
                case 'radio':
                    el.checked = savedValue === 'true';
                    break;
                default:
                    el.value = savedValue;
                    break;
            }
        }
    });

    // Save state
    persistentElements.forEach(el => {
        el.addEventListener('change', () => {
            switch(el.type) {
                case 'checkbox':
                case 'radio':
                    localStorage.setItem(el.id, el.checked);
                    break;
                default:
                    localStorage.setItem(el.id, el.value);
                    break;
            }
        });
    });
});

// We periodically send a heartbeat to the server to keep it alive.
// The server shuts down if it hasn't received a heartbeat in a sufficiently long interval;
// This handles both the case when the browser tab is closed and when the browser is shut down.
function sendHeartbeat() {
    let xhr = new XMLHttpRequest();
    xhr.open("GET", "/heartbeat", true);
    xhr.send();
}

setInterval(sendHeartbeat, 2000); // Send heartbeat every 2 seconds

      window.addEventListener("load", () => {
	  load(profile);
      });
      //load(profile);
    </script>
      <nav class="navbar fixed-bottom navbar-default justify-content-center bg-light bg-opacity-75" style="backdrop-filter: blur(2px);">
	<div class="container justify-content-center">
	  <p class="text-center">
	    <font style="font-size:small">
	      <a href="https://github.com/plasma-umass/scalene">Scalene</a> version 1.5.34, released 2024.01.27
	      &nbsp;|&nbsp;
	      <a href="https://github.com/plasma-umass/scalene/issues/58">share your Scalene success stories</a>
	    </font>
	  </p>
	</div>
      </nav>
  </body>
</html>